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