Семантически они разные; и это важно, потому что это облегчает чтение вашего кода. Когда я вижу семафор, я сразу начинаю думать «об ограниченном объеме общего ресурса». Когда я вижу 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