Примеры реальной жизни для CountDownLatch и CyclicBarrier

Один пример дается одним из наших тренеров, когда он объяснял разницу между CountDownLatch и CyclicBarrier.

CountDownLatch: предположим, что камень может быть поднят на 10 человек, поэтому вы будете ждать всех 10. Тогда только вы можете поднять камень.

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

Если кто-то согласен с этими комментариями, пожалуйста, дайте мне некоторые подробности.

Я уже прочитал API-интерфейс sun для обоих этих классов. Но мне нужно еще несколько объяснений.

Ответы

Ответ 1

Ключевое отличие состоит в том, что CountDownLatch разделяет потоки на официанты и получатели, а все потоки с использованием CyclicBarrier выполняют обе роли.

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

Пример вашей затычки подразумевает, что все десять человек должны подождать, чтобы поднять камень вместе. Это не тот случай. Лучшим примером для реального мира будет экзаменатор, который терпеливо ждет каждого студента, который будет сдавать экзамен. Студенты не ждут, как только они сдадут свои экзамены и смогут уйти. Как только последний студент сдаст экзамен (или истечет срок), суфлер перестает ждать и уходит с тестами.

Ответ 2

В гипотетическом театре

он называется Mutex, если только один человек позволяет смотреть игру
он называется Семафор, если N количество людей позволяет смотреть игру. Если кто-либо покинет Театр во время игры, другому лицу разрешено смотреть игру.
он называется CountDownLatch, если никто не может войти, пока каждый человек не покинет театр. Каждый человек может свободно покинуть театр.
он называется Cyclicbarrier, если театр не начнется, пока каждый человек не войдет в театр. Здесь шоумен не может начать показ, пока весь человек не войдет и не схватит место. Как только игра закончится, тот же барьер будет применяться для следующего показа

Здесь человек - это Thread, Play - ресурс.

Ответ 3

Пример реального мира Я вижу, что на всех ответах фактически отсутствует реальный пример. Как в том, как эти классы могут использоваться в области программного обеспечения

  • CountDownLatch Многопоточный менеджер загрузок. Менеджер загрузки запустит несколько потоков для загрузки каждой части файла одновременно (при условии, что сервер поддерживает несколько потоков для загрузки). Здесь каждый поток будет вызывать метод обратного отсчета инстанцированной защелки. После того, как все потоки завершили выполнение, поток, связанный с защелкой обратного отсчета, будет интегрировать части, найденные в разных частях, в один файл.

  • CyclicBarrier Тот же сценарий, что и выше. Но предположим, что файлы загружаются из P2P. Снова несколько потоков, загружающих куски. Но здесь предположим, что вы хотите, чтобы проверка на доступность загруженных частей выполнялась через определенный промежуток времени. Здесь важную роль играет циклический барьер. После каждого временного интервала каждый поток будет ждать у барьера, чтобы поток, связанный с циклическим устройством, мог выполнять проверку целостности. Эта проверка целостности может выполняться несколько раз благодаря CyclicBarrier

Пожалуйста, исправьте меня, если что-то не подходит.

Ответ 4

Использовать случай 1 Предположим, вы разделили большое задание на 10 небольших задач, каждый из которых - поток. Вы должны дождаться завершения 10 задач из этих потоков, прежде чем рассматривать выполненную работу.

Итак, основной поток инициатора работы инициализирует CountDownLatch для количества используемых потоков, он распределяет задачи по потокам и ждет, чтобы защелка подняла ноль с помощью метода await. Каждый поток исполнителей будет вызывать countDown в конце своей задачи. Наконец, основной поток будет разбухать, когда все потоки закончатся, поэтому он считает, что вся работа выполнена. В этом сценарии используется защелка doneSignal, описанная в javadoc CountDownLatch.

Использовать случай 2 Предположим, вы разделили большое задание на задачи n * m, распределенные по n потокам. m соответствует строке матрицы, и вы должны вычислить сумму для каждой строки. В этом случае потоки должны быть синхронизированы после завершения каждой задачи, чтобы вычислить итоговое значение для строки. В этом случае a CyclicBarrier, инициализированное числом потоков n, используется для ожидания конца каждого вычисления строки (фактически, m раз).

Для сравнения обоих, предполагается, что CountDownLatch используется только один раз, а CyclicBarrier может использоваться столько раз, сколько требуется алгоритму для точки синхронизации для набора потоков.

Ответ 5

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

Ответ 6

Теоретическая разница:

В CountDownLatch основные потоки ждут, пока другие потоки завершат выполнение. В CyclicBarrier рабочие потоки ждут друг друга, чтобы завершить выполнение.

Вы не можете повторно использовать один экземпляр экземпляра CountDownLatch, когда счетчик достигнет нуля, а защелка открыта, с другой стороны, CyclicBarrier может быть повторно использован путем сброса барьера, после того как барьер будет сломан.

Пример реальной жизни: -

CountDownLatch: Рассмотрим сценарий ИТ-мира, где менеджер разделяет модули между командами разработчиков (A и B), и он хочет назначить его команде QA для тестирования только тогда, когда обе команды завершают свою задачу.

Здесь менеджерский поток работает как основной поток, а команда разработчиков работает как рабочий поток. Поток менеджера ожидает, пока поток команд разработчиков завершит выполнение своей задачи.

CyclicBarrier: Рассмотрим один и тот же сценарий ИТ-мира, где менеджер разделяет модули между командами разработчиков (A и B). Он уходит в отставку и просит обе команды ждать друг друга, чтобы выполнить свою задачу, как только оба будут назначены для команды QA для тестирования.

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

Ответ 7

CountDownLatch: Если мы хотим, чтобы все наши потоки выполняли

что-то + обратный отсчет

так что другое ожидание (для того, чтобы число достигло нуля) threads может продолжаться, мы можем использовать обратный отсчет. Все предыдущие потоки, которые действительно делали обратный отсчет, могут продолжаться в этой ситуации, но нет никакой гарантии, что строка , обработанная после latch.countdown(), будет ждать, пока другие потоки достигнут на latch.countdown() но у него есть гарантия, что другие ожидающие потоки начнутся только после того, как latch.await() достигнет нуля.

CyclicBarrier: Если мы хотим, чтобы весь наш поток был

сделать что-то + ждать в общей точке + сделать что-то

(каждый вызов будет уменьшать время ожидания для продолжения потоков)

Функция CyclicBarrier может быть достигнута с помощью CountDownLatch только один раз, вызвав latch.countdown(), за которым следует latch.await() всеми потоками.

но снова вы не можете reset/повторно использовать обратный отсчет.

Лучший пример, где я использовал CyclicBarrier, - это инициализировать несколько кешей (нагретых несколькими потоками), а затем начать дальнейшую обработку, и я снова хотел повторно инициализировать другие тайники в Sync.

Ответ 8

Циклический барьер, как следует из названия, может использоваться в циклах. Например: Я компания hr ищет N количество резюме из различных лент портала вакансий. У меня есть набор навыков, содержащий навыки, отсортированные в порядке приоритета. Для ex java, С#, python. Я хочу найти N резюме, соответствующих набору навыков java, но если я не найду нужного нет. резюме, я снова ищу на следующем наборе навыков и т.д.

Я создаю рабочего, каждый из которого просматривает резюме, в назначенные задания. Оба работника начнут с первичного поиск навыков в своих рабочих местах.

После выполнения поиска работник проверяет, возобновляется ли N были найдены. Если найдется, рабочий будет reset барьером и вернуть. Иначе он будет ждать завершения работы другого работника. Если все же N резюме не были найдены, поиск будет снова возобновлено, на следующем умении в массиве набора навыков. Таким образом, поиск можно называть рекурсивно/циклически, без необходимости создать новый циклический барьер.

Ответ 9

Вот мои наблюдения: -→ 1. После событий завершения: Во время создания событие завершения не может быть передано в CountDownLatch, но оно может быть задано в CyclicBarrier.

  1. Подсчитывает: при создании CyclicBarrier число рабочих потоков не включает основной поток, если он также ожидает завершения других потоков. При создании CountDownLatch просто необходимо указать, сколько рабочих потоков будет ждать основной поток, чтобы завершить. В CountDownLatch существует концепция основного и рабочего потоков, и основной ожидающий поток не учитывается при создании защелки.

  2. Намерение await(): В CyclicBarrier :: await() все потоки, включая основной поток, равны и ждут друг друга. Следовательно, await() следует указывать во всех потоках (как рабочих, так и основных). CountDownLatch :: await() дается только в основном потоке и заставляет основной поток ждать, пока другие рабочие потоки не подсчитают до 0. Таким образом, внутренняя реализация обоих await() отличается.

  3. Стороны и ожидающие потоки: CountDownLatch не может дать число ожидающих потоков, но может дать стороны (cl.getCount()), CyclicBarrier может не дать ожидающих потоков cb.getNumberWaiting() и сторон (cb.getParties())

  4. Рабочие обязанности: рабочий поток в countdownlatch должен выполнять countdown(), а await() - один основной поток. В cyclicBarrier рабочий и основной потоки все делают только await() друг на друга.

  5. Повторное использование: CyclicBarrier можно использовать повторно. cb.await() работает для новых потоков, скажем, t1, t2 и main. И второй вызов cb.await() для новых потоков t3, t4 и main также работает. Main будет ожидать обоих вызовов, то есть система автоматически сбрасывает счет (или сбрасывает()) после выхода из барьера. CountDownLatch не может быть повторно использован. - cl.await() работает для новых потоков, скажем, t1, t2 и main. Основной поток ожидает завершения t1, t2. Но для второго вызова cl.await() новые потоки t3, t4 и main не будут ждать.

Вот код, чтобы поддержать это....

static class MyThread implements Runnable
{
    long waitTime;
    CyclicBarrier cyclicBarrier;
    CountDownLatch countdownlatch;
    MyThread(  long waitTime, CyclicBarrier cyclicBarrier, CountDownLatch countdownlatch){
        this.waitTime = waitTime;
        this.cyclicBarrier = cyclicBarrier;
        this.countdownlatch = countdownlatch;
    }
    @Override
    public void run() {

            try {

                Thread.sleep(waitTime);

                // Diff 4 -----> countdownlatch worker threads need to do countdown and await is done by one single main thread
                //, cyclicBarrier worker threads await on each other
                countdownlatch.countDown(); 
                cyclicBarrier.await();

                System.out.println("cyclicBarrier :: " + 
                        ", name :: " + Thread.currentThread().getName() 
                        + ", parties :: " + cyclicBarrier.getParties() 
                        + ", waiting :: "+ cyclicBarrier.getNumberWaiting()); 

                System.out.println("countdownlatch :: " + 
                            "name :: " + Thread.currentThread().getName()  +
                         ", parties :: "+countdownlatch.getCount() +
                         ", waiting :: " + "No method!!" ); 
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

    }

}

public static class MyCBFinishEvent implements Runnable{

    public void run() {

           System.out.println("All threads have reached common barrier point "
                        + ", CyclicBarrrierFinishEvent has been triggered");
           System.out.println("You can update shared variables if any");
    }

}

public static void main(String [] args) throws InterruptedException, BrokenBarrierException{
    //Diff 1 ----- > No finish event can be given in CountDownLatch
    //Diff 5 ------> CyclicBarrier no of worker threads includes main thread, 
    //CountDownLatch is just how many threads, the main waiting thread is not included in count.
    CyclicBarrier cb = new CyclicBarrier(3, new MyCBFinishEvent());
    CountDownLatch cl = new CountDownLatch(2);

    //Diff 2 ----> CountDownLatch cant give num of waiting threads, CyclicBarrier can getNumberWaiting threads
     System.out.println("Start CyclicBarrier - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("Start CountDownLatch - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

    Runnable t1 = new Thread(new MyThread( 10000, cb, cl));
    Runnable t2 = new Thread(new MyThread( 5000, cb, cl));
     Thread tt1 = new Thread(t1, "t1");
     Thread tt2 = new Thread(t2, "t2");
     tt1.start();
     tt2.start();

     //Diff 6 ---- > await meaning Main waits for t1 and t2 to complete, 
     //CyclicBarrier all are equal. each thread including main thread, if it wants to wait has to do await. 
     //CountDownLatch concept of waiting and workers. main thread await waits till other worker threads make count to 0.
     cb.await();
     cl.await();

     System.out.println("End CyclicBarrier call 1 - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("End CountDownLatch call 1 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     System.out.println("main start created t3, t4 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     Runnable t3 = new Thread(new MyThread( 6000, cb, cl));
        Runnable t4 = new Thread(new MyThread( 100, cb, cl));
         Thread tt3 = new Thread(t3, "t3");

         Thread tt4 = new Thread(t4, "t4");

         tt3.start();
         tt4.start();

        //Diff -3 -----> 
         //CyclicBarrier - can be reused, main thread waited for t3, t4 to complete.
         //CountDownLatch - for first cl.await(), main waited... second cl.await() call main did not wait!!! 
         cb.await();
         cl.await();


         System.out.println("End main - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
         System.out.println("end main parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

}