Ответ
Потокобезопасный класс — это класс, внутреннее состояние которого остаётся консистентным и корректным при одновременном использовании из нескольких потоков без необходимости внешней синхронизации со стороны клиентского кода.
Ключевой признак: Инварианты класса не нарушаются в условиях конкурентного доступа (чтения и записи).
Пример НЕпотокобезопасного и потокобезопасного класса:
// НЕ потокобезопасный счётчик
class UnsafeCounter {
private int value = 0;
public void increment() { value++; } // Операция не атомарна!
public int getValue() { return value; }
}
// Потокобезопасный счётчик с использованием synchronized
class SynchronizedCounter {
private int value = 0;
public synchronized void increment() { value++; } // Блокировка по экземпляру
public synchronized int getValue() { return value; }
}
// Потокобезопасный счётчик с использованием AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;
class AtomicCounter {
private AtomicInteger value = new AtomicInteger(0);
public void increment() { value.incrementAndGet(); } // Атомарная операция CAS
public int getValue() { return value.get(); }
}
Основные стратегии обеспечения потокобезопасности:
- Полная инкапсуляция состояния и использование синхронизации (
synchronizedметоды/блоки,ReentrantLock). - Использование неизменяемых (immutable) объектов. Если состояние объекта не может измениться после создания, он по определению потокобезопасен.
- Использование потокобезопасных классов из
java.util.concurrent:AtomicInteger,AtomicReference(атомарные операции).ConcurrentHashMap,CopyOnWriteArrayList(специализированные коллекции).ThreadLocal(хранение состояния для каждого потока отдельно).
- Правильная публикация объектов (использование
finalполей,volatileпеременных).
Важно: Потокобезопасность — это свойство всего класса, а не отдельных методов. Даже если каждый метод синхронизирован, композиция вызовов (например, «проверить-и-действовать») без внешней синхронизации может привести к состоянию гонки (race condition).