Мне интересно, какой из них лучше на практике и почему?
Я обнаружил, что Lock
и Condition
(и другие новые concurrent
классы)просто больше инструментов для набора инструментов.Я мог делать почти все, что мне было нужно, со своим старым молотком (ключевое слово synchronized
), но в некоторых ситуациях его было неудобно использовать.Некоторые из этих неловких ситуаций стали намного проще, когда я добавил в свой инструментарий больше инструментов: резиновый молоток, молоток с шариковой ручкой, монтировку и несколько ударов по гвоздям. Однако , мой старый молоток все еще видит свою долю использования.
Я не думаю, что один действительно "лучше", чем другой, но каждый лучше подходит для разных задач.,Короче говоря, простая модель и ориентированная на область действия synchronized
помогает защитить меня от ошибок в моем коде, но эти же преимущества иногда являются помехами в более сложных сценариях.Это более сложные сценарии, для которых был создан параллельный пакет.Но использование конструкций более высокого уровня требует более явного и тщательного управления в коде.
===
Я думаю, что JavaDoc хорошо описывает разницу междуLock
и synchronized
(выделение мое):
Реализация блокировки обеспечивает более широкие операции блокировки , чем можно получить с помощью синхронизированных методов изаявления.Они допускают более гибкое структурирование , могут иметь совершенно разные свойства и могут поддерживать несколько связанных объектов Condition .
...
Использование синхронизированных методов или операторов обеспечивает доступ к неявной блокировке монитора, связанной с каждым объектом, но принудительно блокирует все блокировкиполучение и разблокирование происходит в блочной структуре : когда несколько блокировок являются приобретенными они должны быть разблокированы в обратном порядке , а все замки должны быть разблокированы в той же лексической области, в которой они были получены .
Хотя механизм обзора для синхронизированных методов и операторов значительно упрощает программирование с блокировками монитора и помогает избегайте многих распространенных ошибок программирования, связанных с блокировками, в некоторых случаях вынужно работать с замками более гибко.Например, ** некоторые алгоритмы * для обхода одновременно работающих структур данных требуют использования «передачи с руки» или «блокировки цепи» : выполучить блокировку узла A, затем узла B, затем освободить A и получить C, затем освободить B и получить D и так далее.Реализации интерфейса Lock позволяют использовать такие методы с помощью , позволяющие захватывать и снимать блокировку в различных областях и , позволяющий приобретать и снимать несколько замков в любом порядке .
С этим повышенная гибкость дает дополнительную ответственность .Отсутствие блокировки с блочной структурой устраняет автоматическое освобождение блокировок , которое происходит с синхронизированными методами и операторами.В большинстве случаев следует использовать следующую идиому:
...
Когда блокировка и разблокировка происходят в разных областях , необходимо соблюдать осторожность гарантирует , что весь код, который выполняется при удержании блокировки , защищен try-finally или try-catch to обеспечить разблокировку замка при необходимости.
Реализации блокировки предоставляют дополнительные функциональные возможности по сравнению с использованием синхронизированных методов и операторов, предоставляя неблокирующую попытку получения alock (tryLock ()), попытка получить блокировку, которая может быть прервана (lockInterruptibly (), и попытка получить блокировку, которая может истечь (tryLock (long, TimeUnit)).
...