Ребята, может ли кто-нибудь дать простой практический пример использования LockSupport и AbstractQueuedSynchronizer? Пример, приведенный в javadocs, довольно напряжен.
Использование разрешений Semaphore понимается мной.
Спасибо за любой ответ.
Ребята, может ли кто-нибудь дать простой практический пример использования LockSupport и AbstractQueuedSynchronizer? Пример, приведенный в javadocs, довольно напряжен.
Использование разрешений Semaphore понимается мной.
Спасибо за любой ответ.
Если вы говорите об использовании механизма блокировки (или даже барьеров синхронизации), просто используйте java.util.concurrent.Lock. Очевидным предложением является пользователь a ReentrantLock, который делегирует команду Synch. Синхронизация представляет собой AQS, который, в свою очередь, использует LockSupport.
Все это сделано под обложками для вас.
Edit:
Не допускайте практического использования AbstractQueuedSynchronizer (AQS).
Concurrency конструкции могут быть очень разными в их использовании, все могут иметь одни и те же основные функции.
т.е. При некотором состоянии припаркуем эту нить. При каком-то другом условии просыпайтесь вверх.
Это очень широкий набор инструкций, но делает очевидным, что для большинства структур concurrency потребуется какая-то общая функциональность, которая сможет обрабатывать эти операции для них. Введите AQS. Существует пять основных барьеров синхронизации.
ReentrantLockReadLockWriteLockSemaphoreCountDownLatchТеперь все эти пять структур имеют очень различный набор правил при их использовании. 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.