Обратный отсчет против семафора
есть ли какие-либо преимущества использования
java.утиль.параллельный.Обратный отсчет
вместо
java.утиль.параллельный.Семафор?
насколько я могу судить, следующие фрагменты почти эквивалентны:
1. Семафор
final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
}
sem.acquire(num_threads);
2: CountDownLatch за
final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
}
latch.await();
за исключением того, что в случае #2 защелки нельзя использовать повторно, и что еще более важно, вам нужно заранее знать, сколько потоков будет создано (или ждать, пока они все не будут запущены перед созданием защелки.)
Итак, в какой ситуации защелка может быть предпочтительнее?
6 ответов:
обратный отсчет защелки часто используется для полной противоположности вашего примера. Как правило, у вас будет много потоков, блокирующих "await ()", которые будут запускаться одновременно, когда графство достигнет нуля.
final CountDownLatch countdown = new CountDownLatch(1); for (int i = 0; i < 10; ++ i){ Thread racecar = new Thread() { public void run() { countdown.await(); //all threads waiting System.out.println("Vroom!"); } }; racecar.start(); } System.out.println("Go"); countdown.countDown(); //all threads start now!вы также можете использовать это как "барьер" в стиле MPI, который заставляет все потоки ждать, пока другие потоки догонят до определенного момента, прежде чем продолжить.
final CountDownLatch countdown = new CountDownLatch(num_thread); for (int i = 0; i < num_thread; ++ i){ Thread t= new Thread() { public void run() { doSomething(); countdown.countDown(); System.out.printf("Waiting on %d other threads.",countdown.getCount()); countdown.await(); //waits until everyone reaches this point finish(); } }; t.start(); }все сказанное, защелку обратного отсчета можно безопасно использовать в образе вы показывали в вашем примере.
CountDownLatch за используется для запуска серии потоков, а затем ждать, пока все они не будут завершены (или пока они не вызовут
countDown()заданное количество раз.семафор используется для управления количеством параллельных потоков, использующих ресурс. Этот ресурс может быть чем-то вроде файла или может быть процессором, ограничивая количество выполняемых потоков. Счетчик на семафоре может идти вверх и вниз, как разные потоки вызова
acquire()иrelease().в вашем примере Вы по существу используете семафор как своего рода счетчикдощеколду. Учитывая, что ваше намерение состоит в том, чтобы дождаться окончания всех потоков, используя
CountdownLatchделает ваши намерения яснее.
краткий итог:
семафор и CountDownLatch за служит для разных целей.
использовать семафор для управления потоками ресурсов.
использовать CountDownLatch за дождаться завершения всех потоков
семафор определение из javadocs:
A семафор поддерживает набор разрешений. Каждый приобрести() блоки при необходимости до a разрешение доступно, а затем принимает его. Каждый release () добавляет разрешение, потенциально освобождая блокирующего эквайера.
однако фактические объекты разрешений не используются;семафор просто сохраняет количество доступных номеров и действует соответственно.
как это работает ?
семафоры используются для управления количеством параллельных потоков, использующих ресурс.Этот ресурс может быть чем-то вроде общих данных или блока кода (критическая секция) или любой файл.
счетчик на семафоре может идти вверх и вниз, как разные потоки вызова
acquire() иrelease(). Но в любой момент времени у вас не может быть большего количества потоков, чем количество семафоров.Семафор Использовать случаи:
- ограничение одновременного доступа к диску (это может убить производительность за счет конкурирующих на диске)
- ограничение создания потока
- пул соединений JDBC / ограничение
- Сетевые подключения регулирования
- троттлинг процессора или интенсивных операций с памятью
взгляните на это статьи для использования семафора.
CountDownLatch за определение от документации:
средство синхронизации, которое позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.
как это работает?
CountDownLatch за работает с помощью счетчика, инициализированного числом потоков, которое уменьшается каждый раз, когда поток завершает свое выполнение. Когда count достигает нуля, это означает, что все потоки завершили свое выполнение, а поток ожидание на защелке возобновить выполнение.
случаи использования CountDownLatch:
- достижение максимального параллелизма: иногда мы хотим, чтобы начать ряд потоки в то же время для достижения максимального параллелизма
- дождитесь завершения N потоков перед началом выполнения
- обнаружение взаимоблокировок.
взгляните на это статьи чтобы четко понимать концепции обратного отсчета.
есть а посмотрите на Fork Join Pool в этом статьи тоже. Он имеет некоторое сходство с CountDownLatch за.
сказать, что вы ходили в гольф-специализированный магазин, в надежде найти вчетвером,
когда вы стоите в очереди, чтобы получить время тройника от одного из профессиональных продавцов, по сути, вы позвонили
proshopVendorSemaphore.acquire(), Как только вы получите время тройника, вы позвонилиproshopVendorSemaphore.release().Примечание: любой из бесплатных сопровождающих может обслуживать вас, т. е. общий ресурс.теперь вы подходите к стартеру, он начинается с
CountDownLatch(4)и звонкиawait()чтобы дождаться других, со своей стороны вы позвонили в check-in т. е.CountDownLatch.countDown()и так же остальная четверка. Когда все прибывают, стартер дает идти вперед(await()возвращает вызов)теперь, после девяти лунок, когда каждый из вас делает перерыв, гипотетически позволяет включить стартер снова, он использует "новый"
CountDownLatch(4)к тройнику с отверстия 10, такие же ожидание/синхронизация как отверстие 1.однако, если стартер использовал
CyclicBarrierдля начала, он мог бы сбросить тот же экземпляр в отверстие 10 вместо второй защелки, которые используют & throw.
глядя на свободно доступный источник, нет никакой магии в реализации двух классов, поэтому их производительность должна быть примерно одинаковой. Выберите тот, который делает ваше намерение более очевидным.
CountdownLatch заставляет потоки ждать метода await () до тех пор, пока счетчик не достигнет нуля. Поэтому, возможно, вы хотите, чтобы все ваши потоки ждали до 3 вызовов чего-то, тогда все потоки могут идти. А защелку вообще сбросить нельзя.
семафор позволяет потокам извлекать разрешения, что предотвращает одновременное выполнение слишком большого количества потоков, блокируя, если он не может получить разрешения, необходимые для продолжения. Разрешения могут быть возвращены на семафор, позволяющий другие ожидающие потоки для продолжения.
Comments