Порядок возврата монитора на Java - PullRequest
1 голос
/ 15 июля 2011

Ну, я был не прав - приведенное ниже утверждение не относится, не в моих тестовых прогонах.


Это письмо ( wot, без кур?) с JavaСписок рассылки веток довольно старый, фактически он датирован 25 сентября 1996 года. Питер Уэлч обнаружил:

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

Чтобы еще раз обобщить поведение:

Thread-1 acquires the monitor lock
Thread-1 sees the condition is not true yet -> wait()
Thread-0 acquires the monitor lock
Thread-2 contends with Thread-0 for the monitor lock
Thread-3 contends with Thread-0 for the monitor lock
Thread-4 contends with Thread-0 for the monitor lock
Thread-5 contends with Thread-0 for the monitor lock
Thread-0 turns the condition to true -> notifyAll();
Thread-0 released the monitor lock
Thread-4 acquires the monitor lock
Thread-4 enjoys his desirable state
Thread-4 releases the monitor lock
Thread-2 acquires the monitor lock
Thread-2 enjoys his desirable state
...

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

Почему первый поток должен быть тем, который восстанавливает блокировку монитора последним?Способ реализации Thread-1 никогда не может пройти условие и войти в желаемое состояние.

Есть ли какое-то объяснение для этой семантики?

Важно: Этовопрос не в том, могу ли я положиться на механику, которую я обнаружил.Я знаю, как задокументировано ожидание и сигнализация для Java и что в них четко указано, , на это нельзя положиться.Меня интересует, реализуют ли виртуальные машины таким образом, упорядочивают ли потоки определенным образом.

Ответы [ 2 ]

0 голосов
/ 15 июля 2011

Мне нужно было проверить документацию, но я понял, что нет гарантии, какой поток из нескольких претендентов получит блокировку.Это не «первым пришел - первым вышел» или каким-либо таким детерминированным порядком.Если вы хотите, чтобы функция X выполнялась перед функцией Y, не создавайте два отдельных потока.Создайте один поток, который выполняет X, а затем выполняет Y. Вся идея многопоточности заключается в том, что все эти потоки работают независимо.Если вы спрашиваете: «Как я могу убедиться, что поток-1 работает перед потоком-2?», Вы задаете неправильный вопрос.Если код в потоке-1 должен выполняться перед кодом в потоке-2, не делайте их двумя отдельными потоками.Это похоже на старую шутку, пациент: «Доктор, каждый раз, когда я вот так держу руку над головой, я испытываю эту ужасную боль».Доктор: «Так что не держи свою руку над головой вот так».

0 голосов
/ 15 июля 2011

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

Wakes up a single thread that is waiting on this object's monitor. If any threads are
waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and 
occurs at the discretion of the implementation. A thread waits on an object's monitor by 
calling one of the wait methods.

Однако ReentrantReadWriteLock поддерживает политику справедливости, и режим честности описывается как:

When constructed as fair, threads contend for entry using an approximately arrival
order policy. When the currently held lock is released either the longest-waiting
single writer thread will be assigned the write lock, or if there is a group of reader
threads waiting longer than all waiting writer threads, that group will be assigned the read lock.
...