У каждого ли экземпляра есть свой mutex
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Есть ли у каждого экземпляра свой mutex в Java
Да, в Java каждый объект имеет встроенный монитор (mutex), который используется для синхронизации доступа к экземплярным данным. Это фундаментальная концепция многопоточности в Java.
Как работает монитор объекта
Когда вы используете ключевое слово synchronized, вы блокируете монитор конкретного объекта:
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
Counter counter1 = new Counter();
Counter counter2 = new Counter();
В этом примере counter1 и counter2 имеют разные мониторы. Поток может одновременно выполнять increment() на counter1 и counter2, потому что они блокируют разные объекты.
Экземплярные vs классовые мониторы
Экземплярные мониторы:
- Каждый объект создаёт свой монитор в памяти
- Синхронизирует доступ к данным конкретного экземпляра
- Несколько потоков могут параллельно работать с разными экземплярами
public class BankAccount {
private double balance;
public synchronized void deposit(double amount) {
balance += amount;
}
}
BankAccount account1 = new BankAccount();
BankAccount account2 = new BankAccount();
// Два потока могут одновременно вносить деньги на разные счета
Thread t1 = new Thread(() -> account1.deposit(100));
Thread t2 = new Thread(() -> account2.deposit(100));
Классовые мониторы:
- Если метод объявлен как
static synchronized, блокируется монитор класса - Все экземпляры класса используют один монитор
- Потоки не могут работать параллельно с разными объектами
public class GlobalCounter {
private static int total = 0;
public static synchronized void increment() {
total++;
}
}
Явная синхронизация через ReentrantLock
Для более гибкого контроля используют ReentrantLock — явные мониторы:
public class SharedResource {
private final ReentrantLock lock = new ReentrantLock();
private int value = 0;
public void setValue(int newValue) {
lock.lock();
try {
value = newValue;
} finally {
lock.unlock();
}
}
}
SharedResource res1 = new SharedResource();
SharedResource res2 = new SharedResource();
// У каждого экземпляра свой ReentrantLock
Внутреннее устройство
Каждый объект в Java содержит заголовок объекта (object header), где хранится информация о мониторе:
- Identificator блокировки
- Счётчик повторной блокировки (для
ReentrantLock) - Идентификатор потока-владельца
- Состояние монитора (заблокирован/свободен)
Практический пример с проблемой
public class UnsafeCounter {
private int count = 0;
public void increment() {
count++; // НЕ БЕЗОПАСНО! Без монитора
}
}
// Правильно:
public class SafeCounter {
private int count = 0;
public synchronized void increment() {
count++; // Каждый экземпляр защищен своим монитором
}
}
Ответ на вопрос
Да, у каждого экземпляра есть свой встроенный монитор. Это позволяет несколько потокам параллельно работать с разными объектами без блокировки друг друга. Однако если вы используете static synchronized, все экземпляры класса блокируют один общий монитор класса, что снижает параллелизм.