Ответ
Для реализации потокобезопасного счетчика в Java есть несколько основных подходов, выбор зависит от требуемой функциональности и производительности.
| Механизм | Когда использовать | Пример |
|---|---|---|
AtomicInteger |
Для простых атомарных операций (инкремент, декремент). Наиболее эффективный и предпочтительный вариант для счетчика. | ```java |
AtomicInteger counter = new AtomicInteger(0); int newValue = counter.incrementAndGet(); // Потокобезопасно
| **`synchronized`** | Когда операция не сводится к одной атомарной команде (например, нужно проверить условие перед изменением). | ```java
private int count = 0;
public synchronized void incrementIfLessThan(int max) {
if (count < max) {
count++;
}
}
``` |
| **`ReentrantLock`** | Когда требуется более гибкое управление блокировкой: попытка захвата (`tryLock()`), честность (fairness), привязка условий. | ```java
private final Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // Важно освобождать в finally
}
}
``` |
**Рекомендация:** Для типичного счетчика всегда выбирайте **`AtomicInteger`**. Классы из пакета `java.util.concurrent.atomic` используют аппаратные инструкции сравнения-и-обмена (CAS), что обеспечивает высокую производительность без явных блокировок.