Как Условия в Java знают, какой поток вызывать? - PullRequest
0 голосов
/ 06 сентября 2018

Я читаю документацию о состоянии с Java, и у меня возникло недоразумение. Читая их примеры put и take, вы видите, что они имеют в функции put строку кода: notEmpty.signal(), где notEmpty - это условие от lock.

Что мне интересно, если что, если есть несколько потоков, ожидающих сигнала notEmpty. Что происходит в этом случае и какой поток запускается?

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Я думаю, что поток вызывает await () сначала будет запущен первым, и вывод приходит из исходного кода .

Что await () делает?

  1. создать узел ожидания и добавить узел в очередь fifo, поддерживаемую Условие
  2. снять блокировку, вы видите, прежде чем позвонить await () , вам нужно позвонить lock.lock ()
  3. проверить, не вызван ли signal () во время шага 2 другим потоком. если нет, то оставить текущую тему.

Что сделал сигнал () сделать?

  • взять узел в очереди, поддерживаемой Условием , и поместить его в очередь, поддерживаемую Lock , поэтому, если один поток сначала вызовет await () , сначала он попадет в очередь блокировки

Когда пробудится припаркованная нить?

Очевидно, Lock.unlock () будет вызываться после Condition.signal () , Lock.unlock () получит один узел в 1052 * очередь ожидания блокировки от головы до хвоста, см. AbstractQueuedSynchronizer # unparkSuccessor , поэтому, если вы сначала введете очередь блокировки , сначала вы будете запускаться.

0 голосов
/ 07 сентября 2018

Что мне интересно, так это то, что если несколько потоков ожидают сигнала notEmpty. Что происходит в этом случае и какой поток запущен?

Поскольку другие уже ответили, вы не можете знать, какая нить будет запущена.

так что я думаю, что этот подход работает только для двух потоков?

Зависит от того, что означает этот подход. Часто имеет смысл иметь несколько потоков, ожидающих одного и того же условия. Хитрость в том, что, поскольку вы не можете знать, какой поток будет пробужден, вы должны написать свой код таким образом, чтобы он не имел значение , какой поток был пробужден.

Это пример хорошей практики, которой вы должны следовать при написании многопоточного кода, а именно: когда есть работа, которая должна быть выполнена, не должно иметь значения, какой поток выполняет работу.

0 голосов
/ 06 сентября 2018

Системный вызов ОС, которая его обрабатывает. JVM не знает, какой поток, если таковой будет, будет пробужден.

Потоки управляются ОС, а не JVM, поэтому лучшее, что она может сделать, - это делать правильные системные вызовы и позволить ОС делать все остальное.

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