← Назад к вопросам

У каких объектов есть монитор

1.7 Middle🔥 111 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

У всех объектов есть монитор

В Java каждый объект имеет встроенный монитор (англ. monitor), который используется для синхронизации и управления доступом к ресурсам в многопоточной среде. Это фундаментальная часть модели параллелизма Java.

Что такое монитор

Монитор — это механизм, который гарантирует, что только один поток может одновременно выполнять синхронизированный код для конкретного объекта. Он включает:

  • Блокировку (Lock) — контролирует доступ
  • Очередь ожидания — потоки, ожидающие доступа
  • Условные переменные — для взаимодействия потоков

Как использовать монитор

1. Синхронизированные методы

public class BankAccount {
    private int balance = 1000;
    
    // Весь метод защищен монитором объекта
    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdrawn: " + amount);
        }
    }
    
    public synchronized int getBalance() {
        return balance;
    }
}

// Использование
BankAccount account = new BankAccount();
account.withdraw(100);  // Потокобезопасно

За кулисами это эквивалентно:

public void withdraw(int amount) {
    // Автоматически вызывается monitorenter
    synchronized (this) {
        if (balance >= amount) {
            balance -= amount;
        }
    }
    // Автоматически вызывается monitorexit
}

2. Синхронизированные блоки

public class ThreadSafeCounter {
    private int count = 0;
    private final Object lock = new Object();
    
    public void increment() {
        // Защищаем только критическую секцию
        synchronized (lock) {
            count++;
        }
    }
    
    public int getCount() {
        synchronized (lock) {
            return count;
        }
    }
}

Монитор на уровне класса

У классов (объектов типа Class) также есть свой монитор:

public class Singleton {
    private static Singleton instance = null;
    
    // Синхронизированный статический метод
    // Использует монитор объекта Singleton.class
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

// Эквивалентно:
public static Singleton getInstance() {
    synchronized (Singleton.class) {
        if (instance == null) {
            instance = new Singleton();
        }
    }
    return instance;
}

Взаимодействие потоков через монитор

Методы wait(), notify(), notifyAll() работают с монитором:

public class ProducerConsumer {
    private final List<String> queue = new ArrayList<>();
    private final int MAX_SIZE = 5;
    
    public synchronized void produce(String item) throws InterruptedException {
        // Ждём, пока очередь не опустеет
        while (queue.size() >= MAX_SIZE) {
            wait();  // Освобождает монитор и ждёт
        }
        
        queue.add(item);
        System.out.println("Produced: " + item);
        notifyAll();  // Пробуждает ожидающие потоки
    }
    
    public synchronized String consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        
        String item = queue.remove(0);
        System.out.println("Consumed: " + item);
        notifyAll();
        return item;
    }
}

Что можно и нельзя синхронизировать

Можно синхронизировать:

  • Любой объект (String, Integer, пользовательский класс)
  • Класс через его Class объект

Нельзя синхронизировать:

  • Примитивные типы (int, double, boolean)
  • null — вызовет NullPointerException
public class Example {
    private int counter;  // Примитив
    private Integer wrapper;  // Объект — можно
    
    public synchronized void badSync() {
        // synchronized работает на объектах, не на примитивах
        counter++;  // Не защищено синхронизацией
    }
}

Углубленная информация: HotSpot оптимизации

JVM автоматически оптимизирует мониторы:

  • Biased Locking — если поток один, блокировка бесплатна
  • Lightweight Locking — при конфликте переходит на более тяжелую
  • Heavyweight Locking — системная блокировка (mutex)
public class OptimizedMonitor {
    private int value;
    
    public synchronized int getValue() {
        return value;  // HotSpot может оптимизировать
    }
}

Современные альтернативы

Для сложных сценариев используют:

import java.util.concurrent.locks.*;

public class ModernLocking {
    private final ReentrantLock lock = new ReentrantLock();
    private int balance = 1000;
    
    public void withdraw(int amount) {
        lock.lock();
        try {
            if (balance >= amount) {
                balance -= amount;
            }
        } finally {
            lock.unlock();
        }
    }
}

И атомарные переменные:

import java.util.concurrent.atomic.*;

public class AtomicCounter {
    private final AtomicInteger counter = new AtomicInteger(0);
    
    public void increment() {
        counter.incrementAndGet();  // Не требует synchronized
    }
}

Монитор — это основа многопоточности в Java, и понимание его работы критично для написания безопасного кода.