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

Как сделаешь synchronized блок в статическом методе

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

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

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

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

Синхронизация в статических методах Java

Синхронизация в статических методах требует особого внимания, потому что статические члены класса являются общими для всех экземпляров и даже доступны без создания объектов. Есть несколько способов реализации.

Способ 1: Synchronized modifier на методе

Это самый простой и понятный подход — синхронизация происходит на уровне всего метода:

public class Counter {
    private static int count = 0;
    
    // Синхронизируется на объекте Class
    public synchronized static void increment() {
        count++;
    }
    
    public synchronized static int getCount() {
        return count;
    }
}

В этом случае блокировка происходит на объекте Class (Counter.class), и только один поток может находиться в этом методе одновременно.

Способ 2: Synchronized блок с ClassName.class

Этот подход даёт больше гибкости — можно синхронизировать только критическую секцию:

public class BankAccount {
    private static int balance = 1000;
    
    public static void transfer(int amount) {
        System.out.println("Начало операции трансфера");
        
        // Только эта часть потокобезопасна
        synchronized (BankAccount.class) {
            if (balance >= amount) {
                balance -= amount;
                System.out.println("Переведено: " + amount);
            } else {
                System.out.println("Недостаточно средств");
            }
        }
        
        System.out.println("Конец операции трансфера");
    }
    
    public static int getBalance() {
        synchronized (BankAccount.class) {
            return balance;
        }
    }
}

Способ 3: Synchronized с помощью отдельного статического объекта

Иногда нужна более тонкая синхронизация между несколькими методами:

public class SharedResource {
    private static final Object LOCK = new Object();
    private static List<String> items = new ArrayList<>();
    
    public static void addItem(String item) {
        synchronized (LOCK) {
            items.add(item);
            System.out.println("Добавлен: " + item);
        }
    }
    
    public static void removeItem(String item) {
        synchronized (LOCK) {
            items.remove(item);
            System.out.println("Удален: " + item);
        }
    }
}

Это полезно, когда нужно синхронизировать несколько методов без глобальной блокировки класса.

Способ 4: ReentrantLock (современный подход)

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

public class AdvancedCounter {
    private static final ReentrantLock lock = new ReentrantLock();
    private static int count = 0;
    
    public static void increment() {
        lock.lock();
        try {
            count++;
            System.out.println("Счетчик: " + count);
        } finally {
            lock.unlock();
        }
    }
    
    public static int getCountWithTimeout() {
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)) {
                try {
                    return count;
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println("Не удалось получить блокировку");
                return -1;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -1;
        }
    }
}

Практический пример с потокобезопасностью

public class DatabaseConnection {
    private static Connection connection;
    private static final Object connectionLock = new Object();
    
    public static Connection getConnection(String url) {
        synchronized (connectionLock) {
            if (connection == null) {
                try {
                    connection = DriverManager.getConnection(url);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            return connection;
        }
    }
}

Важные моменты

  • synchronized методе: блокировка на Class объекте (ClassName.class)
  • synchronized блоке: блокировка на указанном объекте (обычно Class или создать отдельный Object)
  • ReentrantLock: больше контроля, позволяет попытаться получить блокировку с timeout
  • Производительность: synchronized блоки быстрее, чем синхронизация всего метода

Выбор способа зависит от требований: для простых случаев достаточно synchronized блока, для сложных — используй ReentrantLock с условиями (Condition).