Имеет ли набор ожидания монитора Java приоритет над набором записей? - PullRequest
3 голосов
/ 27 июня 2019

Я хотел бы задать вам вопрос, связанный с многопоточностью в Java.

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

AFAIK, монитор имеет 2 набора потоков:

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

Но как они конкурируют, когда notify / notifyAllназывается?Имеют ли потоки из набора ожидания приоритет при получении монитора над потоками в наборе записей или они перемещаются в набор записей?

Могу ли я быть уверен, что в случае notify следующий выполненный поток будет одним извремя ожидания установлено?

1 Ответ

3 голосов
/ 27 июня 2019

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

Стандартный совет - вызывать wait в цикле, где мы проверяем условие ожидания:

synchronized (lock) {
    while (!condition) {
        lock.wait();
    }
    ...

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

Если вам нужна справедливость, когда вы хотите, чтобы поток с самым длинным ожиданием получил блокировку следующим образом, вы можете попробовать одну из явных блокировок из java.util.concurrent.locks, например ReentrantLock , но прочитайте мелкий шрифт:

Конструктор для этого класса принимает необязательный параметр справедливости. Когда установлено значение true, в условиях конкуренции блокировки блокируют доступ к самому длинному ожидающему потоку. В противном случае эта блокировка не гарантирует какой-либо определенный порядок доступа. Программы, использующие справедливые блокировки, к которым обращаются многие потоки, могут отображать более низкую общую пропускную способность (т.е. медленнее, часто намного медленнее), чем программы, использующие настройку по умолчанию, но имеют меньшие отклонения во времени для получения блокировок и гарантируют отсутствие голодания. Однако обратите внимание, что справедливость блокировок не гарантирует справедливость планирования потоков. Таким образом, один из множества потоков, использующих надежную блокировку, может получить ее несколько раз подряд, в то время как другие активные потоки не выполняются и в настоящее время не удерживают блокировку. Также обратите внимание, что несвязанный метод tryLock не учитывает настройку честности. Он будет успешным, если блокировка доступна, даже если другие потоки ожидают.

...