цикл while в реализации BlockingQueue для Java - PullRequest
0 голосов
/ 23 марта 2012

Недавно я увидел следующую реализацию enqueue для BlockingQueue ( источник )

public synchronized void enqueue(Object item)
throws InterruptedException  {
  while(this.queue.size() == this.limit) {
    wait();
  }
  if(this.queue.size() == 0) {
    notifyAll();
  }
  this.queue.add(item);
}

Почему необходима петля while, и можно while заменить на if (this.queue.size() == this.limit)

Кажется, что метод enqueue синхронизирован, поэтому в теле метода может выполняться только один поток за раз и вызывать wait(). Как только поток уведомлен, не может ли он просто продолжить работу, не проверив условие this.queue.size() == this.limit снова?

Ответы [ 2 ]

5 голосов
/ 23 марта 2012

Документация по Object.wait() объясняет это лучше всего:

Поток также может проснуться без уведомления, прерывания или тайм-аута, так называемого ложного пробуждения. Хотя это редко случается на практике, приложения должны защищаться от него, проверяя условие, которое должно было вызвать пробуждение потока, и продолжая ждать, если условие не выполняется. Другими словами, ожидания всегда должны происходить в циклах, как этот:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }
4 голосов
/ 23 марта 2012

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

Метод wait () фактически освобождает монитор синхронизации, чтобы другие потоки могли работать. Если этого не произойдет, то любой поток, пытающийся удалить материал из очереди, также застрянет, ожидая ввода синхронизированного блока в методе get () (например).

Только один из ожидающих потоков увидит частично пустую очередь.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...