Что делает ReentrantLock#tryLock (long, TimeUnit), когда он пытается получить замок?

что делает реализация ReentrantLock#tryLock (long, TimeUnit), когда она пытается получить блокировку ? Предположим, что поток A acually владеет блокировкой myLock, и поток B называют myLock.tryLock(10,SECONDS), поток B спит или ждет ?

другими словами, была разница в этих 2 реализациях:

1.

while (true)
   try {
     if (readLock.tryLock())
       return;
     MILLISECONDS.sleep(5);
   }catch (InterruptedException e) {}

2.

 while (true)
   try {
     if (readLock.tryLock(5,MILLISECONDS))
       return;
   }catch (InterruptedException e) {}

5 ответов


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

затем, j.u.c.l пакет использует методы LockSupport#park для приостановки потока, а не Thread.sleep. И, как я понимаю, это имеет значение для планировщика потоков,park позволяет снизить задержку, но не уверен, как именно есть.

кроме того, ваш код не имеет никакого смысл, точно такой же эффект может быть достигнут lock() метод.


Он ждет блокировки, и нить спит.

внутренне, если tryLock(long, TimeUnit) метод не может получить блокировку немедленно, он ждет указанного количества времени. Если блокировка становится доступной до этого времени, она немедленно возвращается вместе с блокировкой. Обратите внимание, что в этом случае, когда несколько потоков запрашивают блокировку,ReentrantLock будет случайным образом выбирать нить, чтобы дать блокировку next. Это поведение может быть изменено путем передачи true к значению справедливости в конструкторе new ReentrantLock(true).

второй пример будет проверять блокировку только каждые пять миллисекунд. Если блокировка становится доступной во время сна и передается другому потоку до его пробуждения, этот поток будет недоступен для получения блокировки.

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


технически нет никакой разницы относительно состояния ожидающего потока. Из JavaDoc:

Если блокировка сохранена другим потоком тогда, текущий поток становится отключенным в целях планирования потоков и бездействует [...]

Это очень похоже на то, что происходит в случае сна, но я думаю, мы не можем сказать наверняка, если мы не знаем реализацию.

теперь обратите внимание на эту часть:

[...] лежит в спячке, пока не произойдет одна из трех вещей: Блокировка приобретается текущим потоком; или [...]

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

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

Если эта блокировка была установлена для использования политики справедливого заказа, то доступная блокировка не будет получена, если какие-либо другие потоки ждут блокировки.

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


Я думаю, что второй будет ждать 5 миллисекунд, чтобы получить Блокировку в отличие от первого, который попытается сразу заблокировать. Поэтому поток B будет ждать, если в 5 мс (в течение 5 мс) блокировка не получит блокировку, она вернет false. Обычно нет никакой разницы, если у вас есть 5 мс в таймауте, но если вы увеличите это число, вы получите четкое изображение.

5ms тайм-аут он будет ждать 5ms для блокировки, что означает, если блокировка доступна после 3ms это будет вернитесь через 3 мс с true.


большой справочник о том, как замки и другие примитивы параллелизма реализуются увидеть Шавит и отличные Херлихи искусство многопроцессорного программирования.