2013-08-14 4 views
1

Я понимаю (несколько) особенности jdk 5 ReentrantLock hereЗачем нам нужен замок для реентерабера?

Но почему мы хотели бы блокировку «повторного входа»? Если в потоке уже есть блокировка объекта, зачем ему нужно снова его приобрести?

+0

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

+1

Вопрос не в том, что означает повторное вмешательство, а в том, почему желательно повторное размещение. –

ответ

3

Рассмотрите этот теоретический пример: вы используете блокировку для защиты некоторых внутренних данных при обновлении некоторых элементов в списке в графическом интерфейсе. Вы просматриваете и изменяете элементы. При этом окно списка запускает событие (возможно, событие «Измененное событие» или что-то еще), для которого у вас зарегистрирован обработчик. Этот обработчик также блокирует одну и ту же блокировку для обработки нового элемента. Если блокировка не является рекурсивной, эта нить блокируется при второй попытке получить блокировку.

2

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

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

Существует много случаев, когда код будет вызывать вложенные процедуры в моменты, когда охраняемый ресурс удовлетворяет некоторым, но не всем его инвариантам, и где внешний код может ожидать, что вложенные подпрограммы могут внести в него некоторые изменения, а не другие. В таких случаях блокировка реентера может быть уместной, но необходимо следить за тем, чтобы код не делал то, чего он не должен. Одним из преимуществ блокировок реентера является то, что если код, который делает вложенные вызовы с блокировкой, содержит флаги для указания своих обещаний/требований, а код, который получает блокировку, проверяет эти флаги при записи, можно гарантировать, что флаги будут обрабатываться только в предсказуемых последовательности. Такое было бы невозможно, если бы два разных потока пытались использовать ресурс одновременно.