2014-08-29 4 views
-1

Почему wait() внутри синхронизированного блока? Я имею в виду, что только один поток войдет в синхронизированный блок, так как может другой поток выполнить команду wait()?Зачем ждать внутри синхронизированного?

+2

Какой 'synchronized' блок вы говорите? Ваш вопрос действительно нечеткий (и широкий тоже) ... – BackSlash

+0

Ни один из ответов, здесь или в дубликате, не упоминает ключевую причину: 'notifyAll' будет полным беспорядком без требования переобучения блокировки, прежде чем продолжить , –

+0

Это потому, что, прежде чем вы можете что-то ждать, вы должны убедиться, что что-то еще не произошло. И вы должны убедиться, что это не так, как вы ждёте. Поэтому вы должны держать блокировку, чтобы ждать чего-то - блокировки, которая защищает то, что вы ожидаете от изменения состояния. –

ответ

2
  1. Синхронизированное ключевое слово используется для эксклюзивного доступа.
  2. Чтобы синхронизировать метод, просто добавьте синхронизированное ключевое слово в его объявление. Тогда никакие два вызова синхронизированных методов на одном и том же объекте не могут чередоваться друг с другом.
  3. Синхронизированные операторы должны указывать объект, который обеспечивает внутреннюю блокировку. Когда используется синхронизация (это), вам необходимо избегать синхронизации вызовов других методов объектов.
  4. wait() сообщает вызывающему потоку отказаться от монитора и перейдет в режим сна, пока какой-либо другой поток не войдет в тот же монитор и не вызовет notify().
  5. notify() просыпается первый поток, который вызывает wait() на том же объекте.

Пример:

public class ThreadA { 
    public static void main(String[] args){ 
     ThreadB b = new ThreadB(); 
     b.start(); 

     synchronized(b){ 
      try{ 
       System.out.println("Waiting for b to complete..."); 
       b.wait(); 
      }catch(InterruptedException e){ 
       e.printStackTrace(); 
      } 

      System.out.println("Total is: " + b.total); 
     } 
    } 
} 

class ThreadB extends Thread{ 
    int total; 
    @Override 
    public void run(){ 
     synchronized(this){ 
      for(int i=0; i<100 ; i++){ 
       total += i; 
      } 
      notify(); 
     } 
    } 
} 

Понял от: http://www.programcreek.com/2009/02/notify-and-wait-example/

+0

Почему 'synchronized (this)' вызывается в 'ThreadB'? Разве не только сам поток вызывает run, но и другие потоки? – Artemkller545

+0

Когда я пробовал работать без этого синхронизированного блока, я получил java.lang.IllegalMonitorStateException, это интересно. Когда threadA синхронизируется по b, ему нужна гарантия того, что notify() также синхронизируется, или другой экземпляр может вызвать уведомление. –

0
Why is wait() inside of a synchronized block? 

Поскольку поток должен иметь монитор объекта вы звоните wait() на, в случае синхронизированного метода, то this объект.

I mean, only one thread will enter the synchronized block, so how can the other 
thread execute the wait() instruction? 

Он может не только нить внутри синхронизированного блока может выполнять wait(), позволяя другим потокам, чтобы войти в синхронизированный блок.

+0

«почему [foo.] Wait [required to be] внутри [synchronized (foo)]?» Вы в основном сказали: «Потому что это требует». Лучше ответит _why_. Полный ответ слишком велик для этого пространства, но в двух словах; вызывающий 'foo.wait()' должен ждать некоторого явного, проверяемого условия и, чтобы избежать «потерянных уведомлений», каждый блок кода, который может протестировать или изменить условие (включая официанта), должен быть синхронизирован по тот же замок. Java не может гарантировать, что каждый блок кода синхронизирован, но он делает это для блока, который ждет() s и блока, который уведомляет(). –

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