2016-09-02 6 views
0

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

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

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

+0

Даже если учесть этот вопрос как дубликат, но из-за второго запроса, я этого не делал> Почему он был предназначен для использования только один раз? Я думаю, что легко добавить метод set для сброса счетчика. –

ответ

5

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

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

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

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

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

+0

Спасибо, и почему он был предназначен для использования только один раз? – expoter

+0

@expoter Потому что есть другие классы, которые позволяют повторно использовать. Прочитайте [javadoc] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html): * Это феномен с одним выстрелом - счет не может быть сброшен , Если вам нужна версия, которая сбрасывает счет, подумайте об использовании ['CyclicBarrier'] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html). * – Andreas

4

Семафор с п блоков при 0 достигается.

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

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

+1

@expoter Если вы создаете «Семафор» с разрешениями N *, вы можете ['приобретать()'] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ Semaphore.html # приобретать--) N раз, а номер вызова N + 1 для 'gets()' будет блокироваться, т. Е. Он будет блокировать *, когда * число совпадений достигает нуля. --- Если вы создаете 'CountDownLatch' со счетом N, любой вызов [' await() '] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent /CountDownLatch.html#await--) будет блокировать * до тех пор, пока счетчик не достигнет нуля, т. Е. N вызывает 'countDown()'. --- Полностью разная функциональность. – Andreas

+1

+1 (и я согласен с @Andreas), но как небольшое примечание: 'semaphore.acquire (0)' будет по-прежнему блокироваться до тех пор, пока не будет разрешено не менее 0 разрешений, а семафору разрешено иметь отрицательное количество разрешений, поэтому на самом деле довольно просто использовать Семафор, как в основном «CountUpLatch» (от -numberOfCounts до 0). – yshavit

+0

@ Аndreas действительно; моя формулировка слишком непонятна? Или вы переформулируете немного более четко и технически? –

1

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

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

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

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

Посмотрите на этот вопрос SE для получения более подробной информации:

CountDownLatch vs. Semaphore

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

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

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

Javadocs из CountDownLatch цитаты, что:

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