Что такое оптимистичные и пессимистичные блокировки?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Оптимистичные и пессимистичные блокировки - это подходы к управлению параллельным доступом к общим данным в конкурентных средах (многопоточные приложения, базы данных).
Пессимистичная блокировка:
Предполагает, что конфликты при доступе к данным вероятны. Прежде чем получить доступ к ресурсу, поток или транзакция накладывает на него блокировку (эксклюзивную или разделяемую). Другие потоки, пытающиеся получить к нему доступ, будут ждать, пока блокировка не будет снята.
- Плюсы: Гарантирует целостность данных, проста в реализации при невысокой конкуренции.
- Минусы: Может привести к простоям (блокировкам), снижению пропускной способности при высокой конкуренции (deadlocks).
- Примеры: ключевое слово
synchronizedв Java, блокировки на уровне строк или таблиц в базах данных.
// Пример пессимистичной блокировки в Java
public class Counter {
private int count = 0;
public synchronized void increment() {
count++; // Блокировка на объекте, только один поток может выполнять этот метод одновременно
}
public synchronized int getCount() {
return count;
}
}
Оптимистичная блокировка:
Предполагает, что конфликты при доступе к данным маловероятны. Доступ к данным осуществляется без наложения блокировок. Перед сохранением изменений проверяется, не были ли данные изменены другим потоком с момента их считывания. Если изменения были, операция отменяется и обычно повторяется (retry).
- Плюсы: Высокая пропускная способность при низкой конкуренции, нет проблем с deadlocks.
- Минусы: Могут возникнуть конфликты, требующие повторных попыток, что усложняет логику. Не подходит для операций с долгим выполнением или высокой вероятностью конфликтов.
- Примеры: Compare-And-Swap (CAS) операции, управление версиями (versioning) в базах данных (например, использование столбца версии или временной метки).
// Пример оптимистичной блокировки с использованием CAS (java.util.concurrent.atomic)
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
// Попытка атомарно увеличить значение
// Если значение изменилось между считыванием и попыткой обновления, операция повторится
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
Сравнение:
| Характеристика | Пессимистичная блокировка | Оптимистичная блокировка |
|---|---|---|
| Предположение | Конфликты вероятны | Конфликты маловероятны |
| Подход | Блокировка до доступа | Доступ без блокировки, проверка при записи |
| При высоком темпе конфликтов | Может вызвать блокировки, снизить пропускную способность | Частые перезапуски операций, снизить производительность |
| При низком темпе конфликтов | Может создавать накладные расходы | Высокая пропускная способность |
| Проблема Deadlock | Возможна | Невозможна (с точки зрения конкурентного доступа к ресурсу) |