Порядок выполнения потока Java после разблокировки - PullRequest
5 голосов
/ 11 июня 2011

Допустим, у меня есть 2 потока, t1 и t2 , и объект блокировки m . Поток t1 находится в бесконечном цикле, где на каждой итерации он захватывает блокировку m , выполняет некоторую работу, разблокирует m и немедленно запускается заново. За одну итерацию t2 запрашивает блокировку на m , но блокируется t1 и вынужден ждать. Теперь, когда t1 разблокирует m , гарантируется ли, что t2 получит следующую блокировку на m ? или может t1 ускользнуть от него на следующей итерации?

Как правило, есть ли очередь для ожидающих потоков? Если t1 имеет блокировку, и все остальные потоки, также желающие этой блокировки, будут заблокированы в следующем порядке: t2 , t3 , ..., оставшиеся потоки продолжают выполнение в том порядке, в котором они были заблокированы (например, t2 выполняется, затем t3 и т. д.)?

(Я кратко изучил java-спецификацию и не смог найти ответ. Если он там, пожалуйста, дайте мне знать, и я вернусь, чтобы прочитать более внимательно.)

Спасибо! (Первый ТАК, woohoo!)

Ответы [ 4 ]

2 голосов
/ 11 июня 2011

Да, есть очередь, и она может быть честной или нет.Добросовестные очереди дороже, а несправедливые - быстрее (кто выигрывает CAS, тот выигрывает).проверьте java.util.concurrent.locks.AbstractQueuedSynchronizer для получения дополнительной информации.

будут ли остальные потоки продолжать выполнение в том порядке, в котором они были заблокированы (например, t2 выполняется, затем t3и т. д.)?

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

0 голосов
/ 11 июня 2011

Вы можете гарантировать заказ, используя ярмарку Семафор .Стандартные встроенные блокировки / мониторы Java не справедлива и не ставит ордера в очередь честным способом.

Semaphore sem = new Semaphore(1, true);

//usage:
sem.acquire();
try {
  //holding a lock
  //of course both threads share the same semaphore
} finally {
  sem.release();
}

С теоретически блокировками T1 может снова взять блокировку в следующей итерации после ее освобождения, несмотря на точто Т2 уже ждет этого.Маловероятно, но возможно.

0 голосов
/ 11 июня 2011

Нет, нет гарантии для большинства целей.Вы заметите, что некоторые из абстракций java.util.concurrent предлагают опцию «справедливой блокировки» - которая более или менее гарантирует, что каждый поток, ожидающий блокировки, будет в конечном счете вызван (не конкретный порядок).Без справедливости нет гарантии.ОТО, честность очень дорого.(См. «Параллелизм Java на практике» для некоторых тестов), и, как правило, вероятностная вероятность достаточно высока.

0 голосов
/ 11 июня 2011

Нет, таких гарантий нет. Вы можете посоветовать Java быть объектами ReentrantLock, чтобы быть справедливыми , но это рекомендательное и не гарантирует какой-либо порядок.

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

...