Ответ
Пессимистичная блокировка — это стратегия управления параллельным доступом к данным, основанная на предположении, что конфликты (одновременные попытки изменить одни и те же данные) вероятны. Поэтому перед выполнением операции ресурс явно блокируется, чтобы никто другой не мог его изменить.
Аналогия: Прежде чем войти в комнату, вы запираете дверь снаружи, чтобы никто другой не мог войти, пока вы там находитесь.
Как это работает?
- Транзакция А запрашивает блокировку ресурса.
- Транзакция А получает блокировку и начинает работу с ресурсом.
- Транзакция Б пытается получить доступ к этому же ресурсу, но вынуждена ждать, пока Транзакция А не снимет блокировку.
- Транзакция А завершает работу и освобождает ресурс.
- Транзакция Б получает доступ.
Пример в SQL (PostgreSQL):
BEGIN;
-- Блокируем строку с id = 1 до конца транзакции
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- Выполняем операции...
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT; -- Снимаем блокировку
Пример в Go с sync.Mutex
:
var accountMutex sync.Mutex
func withdraw(amount int) {
accountMutex.Lock() // Захватываем мьютекс (блокируем)
defer accountMutex.Unlock() // Гарантируем освобождение в конце функции
// ... логика снятия средств (критическая секция) ...
}
Отличие от оптимистичной блокировки
Оптимистичная блокировка, наоборот, исходит из предположения, что конфликты маловероятны. Ресурс не блокируется. Вместо этого перед обновлением проверяется, не изменил ли кто-то другой данные за время их чтения.
- Как работает: Используется версионирование (например, поле
version
илиupdated_at
).- Читаем данные вместе с их версией (например,
version = 5
). - Выполняем вычисления.
- Пытаемся обновить данные с условием
WHERE id = 1 AND version = 5
. - Если строка обновилась — отлично. Если нет (0 строк обновлено), значит, кто-то другой уже изменил данные (версия стала
6
), и нашу транзакцию нужно повторить или отменить.
- Читаем данные вместе с их версией (например,
Характеристика | Пессимистичная блокировка | Оптимистичная блокировка |
---|---|---|
Основное допущение | Конфликты вероятны | Конфликты маловероятны |
Механизм | Блокировка ресурса перед операцией | Проверка на изменения перед записью |
Производительность | Ниже при малом количестве конфликтов (из-за ожидания) | Выше при малом количестве конфликтов |
Сложность | Риск взаимоблокировок (deadlocks) | Требует логики повторных попыток |
Когда использовать | Высокая конкуренция за данные, цена конфликта высока | Низкая конкуренция, операции чтения преобладают над записью |