Ребята, может ли кто-нибудь дать простой практический пример использования LockSupport
и AbstractQueuedSynchronizer
? Пример, приведенный в javadocs, довольно напряжен.
Использование разрешений Semaphore
понимается мной.
Спасибо за любой ответ.
Ребята, может ли кто-нибудь дать простой практический пример использования LockSupport
и AbstractQueuedSynchronizer
? Пример, приведенный в javadocs, довольно напряжен.
Использование разрешений Semaphore
понимается мной.
Спасибо за любой ответ.
Если вы говорите об использовании механизма блокировки (или даже барьеров синхронизации), просто используйте java.util.concurrent.Lock
. Очевидным предложением является пользователь a ReentrantLock
, который делегирует команду Synch
. Синхронизация представляет собой AQS, который, в свою очередь, использует LockSupport
.
Все это сделано под обложками для вас.
Edit:
Не допускайте практического использования AbstractQueuedSynchronizer
(AQS).
Concurrency конструкции могут быть очень разными в их использовании, все могут иметь одни и те же основные функции.
т.е. При некотором состоянии припаркуем эту нить. При каком-то другом условии просыпайтесь вверх.
Это очень широкий набор инструкций, но делает очевидным, что для большинства структур concurrency потребуется какая-то общая функциональность, которая сможет обрабатывать эти операции для них. Введите AQS. Существует пять основных барьеров синхронизации.
ReentrantLock
ReadLock
WriteLock
Semaphore
CountDownLatch
Теперь все эти пять структур имеют очень различный набор правил при их использовании. A CountDownLatch
может позволить многим потокам запускаться одновременно, но заставляет один (или более) потоки ждать, пока хотя бы n количество потоков не обратится к указанной защелке.
ReentrantLock
заставляет только один поток заходить в критический раздел и ставит в очередь все остальные потоки, чтобы дождаться завершения.
ReadLock
позволяет любое количество потоков чтения в критический раздел до тех пор, пока не будет сохранена блокировка записи.
Примеры могут продолжаться, но большая картина здесь - все они используют AQS. Это связано с тем, что они могут использовать примитивные функции, которые предлагает AQS и реализует более сложные функции поверх нее. AQS позволяет вам парковать непокрытые и просыпающиеся потоки (прерываясь, если нужно), но таким образом, чтобы вы могли поддерживать множество сложных функций.
они не предназначены для прямого использования в клиентском коде; больше за помощь в создании новых параллельных классов.
AQS - замечательный класс для создания примитивов concurrency, но он сложный и требует небольшого изучения, чтобы использовать его правильно. Я использовал его для нескольких вещей, таких как ленивая инициализация и простой быстрый многоразовая защелка.
Как ни крути, я не думаю, что AQS особенно расплывчата, у него отличные джавадоки, описывающие, как правильно его использовать.
2.7 релиз Disruptor использует LockSupport.parkNanos вместо Thread.sleep для уменьшения латентности:
AFAIK, AbstractQueuedSynchronizer используется для управления переходами состояний. JDK использует его для расширения Sync, внутреннего класса для java.util.concurrent.FutureTask. Класс Sync управляет состояниями (READY, RUNNING, RAN и CANCELED) FutureTask и переходами между ними.
Это позволяет, как вы знаете, FutureTask блокировать на FutureTask.get(), пока не будет достигнуто состояние RAN.