Sobes.tech
Senior

Hai mai dovuto usare primitive di sincronizzazione nella programmazione multithread? Parlami di CountDownLatch, CyclicBarrier, Phaser e altri.

sobes.tech AI

Risposta dell'AI

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

CountDownLatch — это счетчик, который позволяет одному или нескольким потокам ждать, пока другие потоки выполнят определённое количество операций. Например, если у вас есть 3 потока, которые должны завершить подготовку, а главный поток ждёт их завершения, то CountDownLatch инициализируется значением 3, и каждый поток вызывает countDown() по окончании работы. Главный поток вызывает await() и блокируется, пока счетчик не станет 0.

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

Phaser — более гибкий примитив, объединяющий возможности CountDownLatch и CyclicBarrier. Позволяет динамически добавлять и удалять участники, поддерживает несколько фаз синхронизации.

Пример использования CountDownLatch на Java:

CountDownLatch latch = new CountDownLatch(3);

Runnable task = () -> {
    // Выполнение задачи
    System.out.println(Thread.currentThread().getName() + " готов");
    latch.countDown();
};

new Thread(task).start();
new Thread(task).start();
new Thread(task).start();

latch.await(); // Ждем, пока все три потока вызовут countDown
System.out.println("Все потоки готовы, продолжаем работу");

Другие примитивы: семафоры (Semaphore) для ограничения количества одновременно работающих потоков, мьютексы (Mutex) для взаимного исключения доступа к ресурсам.