Ответ
Mutex (Mutual Exclusion — взаимное исключение) — это примитив синхронизации, предназначенный для решения проблемы гонки данных (race condition) при доступе нескольких потоков к общему ресурсу (переменной, структуре данных, файлу, устройству).
Решаемая проблема: Без синхронизации два потока могут читать и модифицировать общие данные одновременно, что приводит к непредсказуемому и некорректному результату.
Принцип работы: Mutex обеспечивает, что только один поток может владеть блокировкой (войти в критическую секцию) в любой момент времени. Другие потоки, пытающиеся захватить тот же мьютекс, будут заблокированы до его освобождения.
Пример проблемы (race condition) и решения с помощью ReentrantLock в Java:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int value = 0;
private final Lock lock = new ReentrantLock(); // Создаем мьютекс
// НЕПРАВИЛЬНО: Без синхронизации
public void unsafeIncrement() {
value++; // Операция не атомарна (чтение-изменение-запись)
}
// ПРАВИЛЬНО: Использование мьютекса для защиты критической секции
public void safeIncrement() {
lock.lock(); // Захватываем блокировку
try {
value++; // Критическая секция
} finally {
lock.unlock(); // Всегда освобождаем блокировку в finally
}
}
public int getValue() {
return value;
}
}
Преимущества ReentrantLock перед synchronized:
tryLock(): Попытка захвата блокировки с таймаутом или без, что позволяет избежать deadlock.lockInterruptibly(): Захват блокировки с возможностью прерывания потока.- Честность (fairness): Можно создать "честный" мьютекс, который отдает блокировку самому долго ожидающему потоку.
- Поддержка нескольких Condition: Более гибкое управление ожиданием потоков.
Ключевое правило: Критическая секция под блокировкой должна быть как можно короче, чтобы минимизировать contention (соревнование потоков).