В чем смысл CountDownLatch в Java?

CountDownLatch в java - это утилита синхронизации высокого уровня, которая используется для предотвращения начала обработки определенного потока до тех пор, пока все потоки не будут готовы.

Но Semaphore может делать то же самое. Итак, в чем заслуга CountDownLatch?

Еще один вопрос: если у CountDownLatch есть какие-то достоинства, Почему он был разработан для использования только один раз? Я думаю, что легко добавить метод установки для сброса счетчика.


person expoter    schedule 02.09.2016    source источник
comment
Хотя я хотел отметить этот вопрос как повторяющийся, но из-за второго запроса я не сделал этого ›Почему он был разработан для использования только один раз? Я думаю, что легко добавить метод набора для сброса счетчика.   -  person Ravindra babu    schedule 02.09.2016


Ответы (3)


Семантически они разные; и это важно, потому что это облегчает чтение вашего кода. Когда я вижу семафор, я сразу начинаю думать «об ограниченном объеме общего ресурса». Когда я вижу CountDownLatch, я сразу начинаю думать «куча потоков, ожидающих начала работы!» сигнал ". Если вы дадите мне первое в коде, которому действительно нужно второе, это сбивает с толку.

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

С точки зрения более прагматичного использования CountDownLatch проще, если это все, что вам нужно. Проще лучше!

Что касается повторного использования CountDownLatch, это усложнит его использование. Например, предположим, что вы пытаетесь поставить в очередь потоки A, B и C для некоторой работы. Вы заставляете их ждать на защелке, а затем отпускаете ее. Затем вы сбрасываете его, предположительно, чтобы поставить в очередь потоки D, E и F для какой-то другой работы. Но что произойдет, если (из-за состояния гонки) поток B еще не был освобожден от первой защелки? Что, если он еще даже не дошел до вызова await()? Вы закрываете на нем ворота и приказываете ждать с D, E и F второго открытия? Это может даже вызвать тупик, если второе открытие зависит от работы, которую должен делать B!

У меня были те же вопросы о сбросе настроек, что и у вас, когда я впервые прочитал о CountDownLatch. Но на практике я редко даже хотел сбросить его; каждая единица «подожди, потом иди» (A-B-C, затем D-E-F) естественным образом поддается созданию собственного CountDownLatch, чтобы работать вместе с ним, и все остается простым и красивым.

person yshavit    schedule 02.09.2016
comment
Спасибо, а почему он был разработан для использования только один раз? - person expoter; 02.09.2016
comment
@expoter Потому что есть другие классы, допускающие повторное использование. Прочтите javadoc: Это одноразовое явление - счетчик не может быть сброшен. Если вам нужна версия, которая сбрасывает счетчик, рассмотрите возможность использования _ 1_. - person Andreas; 02.09.2016

Семафор с n блоками при 0.

Достигнут CountDownLatch из n блоков до 0. Затем все продолжаются примерно в одно и то же время.

Таким образом, семафор похож на привратника на дискотеке, а обратный отсчет - это как стартовый выстрел на игровом поле.

person Joop Eggen    schedule 02.09.2016
comment
@expoter Если вы создаете Semaphore с N разрешениями, вы можете _ 2_ N раз, и вызовы с номерами N + 1 на acquire() будут заблокированы, т. е. будут заблокированы только , когда количество разрешений достигнет нуль. --- Если вы создаете CountDownLatch со счетчиком N, любой вызов _ 5_ будет блокировать , пока счетчик не достигнет нуля, то есть N вызовов countDown(). --- Совершенно другой функционал. - person Andreas; 02.09.2016
comment
+1 (и я согласен с @Andreas), но в качестве небольшого примечания: semaphore.acquire(0) будет по-прежнему блокироваться до тех пор, пока не будет как минимум 0 разрешений, а семафор может иметь отрицательное число разрешений, поэтому на самом деле довольно легко использовать Семафор как в основном CountUpLatch (отсчет от -numberOfCounts до 0). - person yshavit; 02.09.2016
comment
@Andreas действительно; моя формулировка слишком непонятна? Или вы переформулируете более четкие и технические детали? - person Joop Eggen; 02.09.2016
comment
@JoopEggen OP прокомментировал, что не понимает, поэтому я пояснил. Этот комментарий исчез. - person Andreas; 02.09.2016
comment
@yshavit a Semaphore действительно является своего рода анти-материей CountDownLatch, к сожалению, должно быть возможно не только отрицательное количество разрешений, но также необходимо увеличить количество приобретаемых или заблокировать выпуск. Но хорошо иметь представление о таких концепциях. - person Joop Eggen; 02.09.2016
comment
Я не понимаю, что вы имеете в виду. Если вы создадите семафор с -3 разрешениями (что вы можете сделать), то любое количество вызовов на получение (0) будет заблокировано до тех пор, пока вы не вызовете release () 3 раза. - person yshavit; 02.09.2016
comment
Итак, каждый поток (который должен запускаться одновременно) вызывает Release + Acquisition? Извините, @yshavit, теперь я глубоко вовлечен в другую проблему, связанную с БД, так что вы можете быть полностью правы. Спасибо за ответ. - person Joop Eggen; 02.09.2016
comment
Нет, я не это имел в виду. Очень простая замена: countDown () превращается в release (), а await () превращается в acqu (0). Такое простое регулярное выражение могло это сделать. :) - person yshavit; 02.09.2016
comment
@yshavit ага, хорошо. - person Joop Eggen; 02.09.2016

Семафор может делать то же самое. Итак, в чем смысл CountDownLatch?

Semaphore поддерживает набор разрешений. Каждый acquire() блокирует при необходимости до тех пор, пока не будет предоставлено разрешение, а затем забирает его. Каждый release() добавляет разрешение, потенциально освобождая блокирующего покупателя.

Однако фактические разрешительные объекты не используются; Семафор просто ведет подсчет доступного числа и действует соответственно.

Semaphore блокирует вход для входа в критический раздел, а CountDownLatch блокирует выполнение основного потока, если другие потоки не завершат свои задачи.

Взгляните на этот вопрос SE для более подробной информации:

CountDownLatch против семафора

Если у CountDownLatch есть какие-то моменты, почему он был разработан для использования только один раз?

Если вы хотите использовать его повторно, используйте CyclicBarrier

Средство синхронизации, которое позволяет набору потоков ждать друг друга, чтобы достичь общей точки барьера. CyclicBarriers полезны в программах, включающих группу потоков фиксированного размера, которые время от времени должны ждать друг друга. Барьер называется циклическим, потому что его можно повторно использовать после освобождения ожидающих потоков.

Документы Javadocs CountDownLatch цитируют следующее:

CountDownLatch - это одноразовое явление - счетчик не может быть сброшен. Если вам нужна версия, которая сбрасывает счетчик, рассмотрите возможность использования CyclicBarrier.

person Ravindra babu    schedule 02.09.2016