Запутался в решении производителя-потребителя (уточнение синхронизации) - PullRequest
3 голосов
/ 12 декабря 2011

Я изучал параллелизм в Java и столкнулся с проблемой производителя-потребителя. Это очевидно стандартно, и я видел почти идентичный ответ во многих местах.

public synchronized void put(int num){
    while (!empty) {
        try{
            wait(); }
        catch {}
    }

    buffer=num;
    empty=false;
    notify();
}

public synchronized int take(){
    while (empty) {
        try{
            wait(); }
        catch {}
    }

    empty=true;
    notify();
    return buffer;
}

Насколько я понимаю, синхронизированный объект использует блокировку на уровне объекта, а это означает, что потоки не могут быть ни помещены, ни помещены, ни взяты. Но оба метода ждут другого метода. Вот где я запутался: кажется, это создает тупик. Если поток А перейдет в пут while empty=false, он будет ждать. Тем не менее, поток B не может ввести take, потому что он синхронизирован. Поэтому пустое навсегда останется ложным, что приведет к тупику.

Учитывая, сколько раз я в основном видел этот ответ, однако, похоже, что он должен быть правильным. Что я не так понимаю?

Спасибо!

1 Ответ

4 голосов
/ 12 декабря 2011

Вызов wait снимет блокировку, полученную при входе в метод. Поэтому, если A ввел put и вызвал wait, блокировка снята, и B может затем продолжить работу внутри take.

Из Javadoc :

The current thread must own this object's monitor. The thread releases ownership 
of this monitor and waits until another thread notifies threads waiting on this 
object's monitor to wake up either through a call to the notify method or the 
notifyAll method. The thread then waits until it can re-obtain ownership of the 
monitor and resumes execution. 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...