Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Виды Мониторов в Java
Мониторы — это механизм синхронизации, обеспечивающий взаимное исключение и видимость памяти при доступе к общим ресурсам из нескольких потоков.
Встроенный монитор (Intrinsic Lock)
Встроенный монитор реализован непосредственно в объекте Java и использует ключевое слово synchronized. Каждый объект имеет ассоциированный монитор.
public class Counter {
private int count = 0;
// Синхронизированный метод
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
Можно также синхронизировать блоки кода:
public class Buffer {
private List<String> items = new ArrayList<>();
public void add(String item) {
synchronized(this) {
items.add(item);
}
}
}
Синхронизация статических методов использует монитор класса:
public class Logger {
private static int logCount = 0;
public static synchronized void log(String message) {
logCount++;
System.out.println(message);
}
}
ReentrantLock
ReentrantLock — это явная реализация интерфейса Lock из пакета java.util.concurrent.locks. Она более гибкая, чем встроенный монитор.
import java.util.concurrent.locks.ReentrantLock;
public class BankAccount {
private double balance = 0;
private final ReentrantLock lock = new ReentrantLock();
public void deposit(double amount) {
lock.lock();
try {
balance += amount;
} finally {
lock.unlock();
}
}
public double getBalance() {
lock.lock();
try {
return balance;
} finally {
lock.unlock();
}
}
}
Преимущества ReentrantLock:
- Явная разблокировка в finally блоке (безопаснее)
- Try-lock с таймаутом
- Справедливая очередь (fair mode)
- Несколько условных переменных (Condition)
public class Producer {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private Queue<String> buffer = new LinkedList<>();
private static final int CAPACITY = 10;
public void produce(String item) throws InterruptedException {
lock.lock();
try {
while (buffer.size() >= CAPACITY) {
notFull.await();
}
buffer.add(item);
notFull.signalAll();
} finally {
lock.unlock();
}
}
}
ReadWriteLock
ReadWriteLock позволяет нескольким читателям одновременно, но только одному писателю:
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Cache {
private Map<String, String> data = new HashMap<>();
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
public String get(String key) {
rwLock.readLock().lock();
try {
return data.get(key);
} finally {
rwLock.readLock().unlock();
}
}
public void put(String key, String value) {
rwLock.writeLock().lock();
try {
data.put(key, value);
} finally {
rwLock.writeLock().unlock();
}
}
}
StampedLock
StampedLock — это оптимистичный замок для лучшей производительности при большом количестве читателей:
import java.util.concurrent.locks.StampedLock;
public class Point {
private double x, y;
private final StampedLock lock = new StampedLock();
public double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead();
double currentX = x;
double currentY = y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}
Сравнение мониторов
| Вид | Скорость | Справедливость | Гибкость |
|---|---|---|---|
| Synchronized | Быстро | Нет гарантий | Низкая |
| ReentrantLock | Нормально | Конфигурируется | Высокая |
| ReadWriteLock | Хорошо для читателей | Нет | Средняя |
| StampedLock | Очень быстро | Нет | Сложная |
Рекомендации
- Используй
synchronizedдля простых случаев ReentrantLockдля сложной синхронизацииReadWriteLockпри доминирующем чтенииStampedLockпри экстремальных требованиях к производительности