2010-11-28 3 views
2

Тема 1:Простой Java параллелизм вопрос

if(!conditionFullfiled) this.wait(); 

Тема 2:

if(conditionFullfiled) thread1.notify(); 

Я хочу просыпаться нить 1 из нити 2, когда некоторое условие fullfiled. Но нет ли проблемы, когда thread1.notify() называется if(!conditionFullfiled) ***HERE*** this.wait();?

ответ

3

Чтобы сделать obj.wait() и obj.notify(), вам необходимо владеть монитором объекта, который вы собираетесь ждать/уведомлять. В вашем коде вы, вероятно, не хотите thread1.notify(). Пример:

Object someSharedObject = ... 

Резьба1:

synchronized(someSharedObject) { 
    // while NOT if for spurious wake ups. 
    while(!conditionFullfiled) someSharedObject.wait(); 
    } 

Резьба2:

synchronized(someSharedObject) { 
    if(conditionFullfiled) someSharedObject.notify(); // this wakes thread1 
    } 

Замок synchronized находится на someSharedObject (может быть this), что означает, что два потока никогда не будет сталкиваться. .wait() освобождает текущий монитор, поэтому Thread2 не будет заблокирован, когда Thread1 ждет.

Редактировать: Я узнал кое-что о ложных пробуждениях. .wait() должен выполняться в петле while - недостаточно if. Why do threads spontaneously awake from wait()?. Спасибо Энно Шиодзи за то, что вы меня учили.

Редактировать: Уточненный .wait() релизы монитор.

+0

`if` следует заменить` while` на справиться с ложными пробуждениями. – 2010-11-28 12:38:03

0

Какой объект вы используете как «это»? Если вы вызываете ожидания() на thread1 объекте, и оба заявления вы показали, завернутые в петле, как это:

new Runnable() { 
    synchronized (thread1) { 
     thread1.wait() 
    } 
} 

Тогда ваш код будет работать, как вы хотите. (Первая строка будет остановлена, когда условие будет ложным и будет работать иначе). Фокус в том, что взаимодействия с объектом потока синхронизированы, поэтому один поток не может прерывать, пока другой работает с объектом.

EDIT: Будет еще лучше, если вы синхронизируете не поток, а какой-либо другой объект (вы можете просто создать чистый объект для обеспечения блокировок).

0

Проблем нет, так как дождаться освобождения блокировки объекта (в случае этого).

Лучше всего защищать условия ожидания/уведомления в блоках - чтобы избежать побочных пробуждений.

3

У вас есть 2 проблемы.

  1. Вы не должны вызывать wait() и уведомлять() о самом объекте нити. Лучший способ сделать это - использовать специальный объект блокировки, например.

    private Object lock = new Object(); ...... lock.wait();

  2. Следующая проблема заключается в том, что вы должны назвать как ожидание() и уведомить в synchornized блок, т.е.

    синхронизирована (замок) { // некоторый код lock.wait(); }

то в другом месте в коде сказать:

syncronized(lock) { 
    lock.notify(); // this line will cause the wait to terminate and the first thread to continue. 
} 

удобно локализовать как wait() и notify() методы обертывания в одном классе, поэтому у них есть доступ, чтобы заблокировать объект.

Для получения более подробной информации читайте http://download.oracle.com/javase/6/docs/api/ http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html

Смежные вопросы