Ответ
Пессимистическая блокировка предполагает, что конфликт при совместном доступе к ресурсу вероятен, поэтому поток заранее захватывает эксклюзивную блокировку.
1. На уровне языка (синхронизация)
Использование ключевого слова synchronized или класса ReentrantLock из java.util.concurrent.locks.
Пример с ReentrantLock:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PessimisticCounter {
private int value = 0;
private final Lock lock = new ReentrantLock(); // Пессимистическая блокировка
public void safeIncrement() {
lock.lock(); // Захват блокировки. Поток будет ждать, если блокировка у другого.
try {
value++; // Критическая секция защищена
} finally {
lock.unlock(); // ОСВОБОЖДЕНИЕ в finally — ОБЯЗАТЕЛЬНО!
}
}
public int getValue() {
lock.lock();
try {
return value;
} finally {
lock.unlock();
}
}
}
2. На уровне базы данных (JDBC)
Использование SELECT ... FOR UPDATE для блокировки строк.
Пример с JDBC и транзакцией:
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false); // Начало транзакции
// 1. ПЕССИМИСТИЧЕСКАЯ БЛОКИРОВКА строки
String selectSQL = "SELECT balance FROM accounts WHERE id = ? FOR UPDATE";
PreparedStatement selectStmt = conn.prepareStatement(selectSQL);
selectStmt.setInt(1, accountId);
ResultSet rs = selectStmt.executeQuery();
// Строка с accountId теперь заблокирована для других транзакций
// 2. Чтение и модификация данных
int currentBalance = 0;
if (rs.next()) {
currentBalance = rs.getInt("balance");
}
rs.close();
selectStmt.close();
int newBalance = currentBalance - 100;
// 3. Обновление заблокированной строки
String updateSQL = "UPDATE accounts SET balance = ? WHERE id = ?";
PreparedStatement updateStmt = conn.prepareStatement(updateSQL);
updateStmt.setInt(1, newBalance);
updateStmt.setInt(2, accountId);
updateStmt.executeUpdate();
updateStmt.close();
conn.commit(); // Фиксация транзакции и снятие блокировки
} catch (SQLException e) {
conn.rollback(); // Откат в случае ошибки
throw e;
} finally {
conn.setAutoCommit(true);
conn.close();
}
| Сравнение с оптимистической блокировкой: | Аспект | Пессимистическая | Оптимистическая |
|---|---|---|---|
| Философия | Конфликты часты, блокируем заранее. | Конфликты редки, проверяем при коммите. | |
| Механизм | synchronized, Lock, FOR UPDATE. |
Версионность (version column), CAS. |
|
| Производительность | Может быть ниже из- ожидания блокировок. | Выше при низкой конкуренции. | |
| Применение | Высокая конкуренция, критичные данные. | Чтение >> записи, низкая конкуренция. |