Вопрос проверяет умение корректно синхронизировать доступ к общему ресурсу в многопоточной среде при использовании CountDownLatch.
Чтобы избежать состояния гонки при работе с не-атомарным счётчиком, используйте:
synchronized-блоки для синхронизации доступа к счётчику.
Лок на объекте, общем для всех потоков.
Проблема возникает, когда несколько потоков одновременно изменяют общий счётчик без синхронизации.
Пример некорректного кода:
int counter = 0;
CountDownLatch latch = new CountDownLatch(4);
for (int i = 0; i < 4; i++) {
new Thread(() -> {
counter++; // Небезопасно!
latch.countDown();
}).start();
}
latch.await();
System.out.println(counter); // Может вывести 1, 2, 3 или 4Решение:
Синхронизация через synchronized:
Object lock = new Object();
// ...
synchronized (lock) {
counter++;
}Использование ReentrantLock:
Lock lock = new ReentrantLock();
// ...
lock.lock();
try {
counter++;
} finally {
lock.unlock();
}Когда использовать:
Если нельзя заменить счётчик на AtomicInteger.
Когда требуется явный контроль над блокировками.