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

Что пишется в круглых скобках вместе с sinchronized

1.3 Junior🔥 141 комментариев
#Многопоточность

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

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

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

# synchronized: что пишется в скобках

В скобках указывается объект, на котором устанавливается блокировка (монитор). Это критически важный момент.

Синхронизация на методе

public synchronized void transfer(Account from, Account to, double amount) {
    // автоматически синхронизируется на this (сам объект)
}

Эквивалентно:

public void transfer(Account from, Account to, double amount) {
    synchronized(this) {
        // тело метода
    }
}

Синхронизация на объекте (instance lock)

private Object lock = new Object();

public void criticalSection() {
    synchronized(lock) { // синхронизируется на объект lock
        // только один поток может быть здесь одновременно
    }
}

Синхронизация на this

public void transfer(Account from, Account to, double amount) {
    synchronized(this) { // синхронизируется на текущий объект
        from.withdraw(amount);
        to.deposit(amount);
    }
}

Синхронизация на классе (class lock)

public static synchronized void globalOperation() {
    // синхронизируется на класс
}

// Эквивалентно:
public static void globalOperation() {
    synchronized(ClassName.class) {
        // тело метода
    }
}

Практический пример: проблема без синхронизации

public class BankAccount {
    private int balance = 1000;
    
    // Опасно! Race condition
    public void withdraw(int amount) {
        balance -= amount;
    }
    
    // Правильно
    public synchronized void withdrawSafe(int amount) {
        balance -= amount;
    }
    
    // Или так
    public void withdrawSafeBlock(int amount) {
        synchronized(this) {
            balance -= amount;
        }
    }
}

Выбор объекта для синхронизации

1. synchronized(this) — синхронизация на объект

public class UserService {
    private List<User> users = new ArrayList<>();
    
    public void addUser(User user) {
        synchronized(this) {
            users.add(user);
        }
    }
}

Проблема: все методы объекта блокируют друг друга, даже если работают с разными данными.

2. synchronized на отдельный объект (лучше)

public class UserService {
    private List<User> users = new ArrayList<>();
    private Object usersLock = new Object();
    
    public void addUser(User user) {
        synchronized(usersLock) {
            users.add(user);
        }
    }
}

Преимущество: другие методы не блокируются.

3. synchronized на List (иногда)

List<String> syncList = Collections.synchronizedList(new ArrayList<>());
synchronized(syncList) {
    // итерирование по синхронизированному списку
    for (String item : syncList) {
        // ...
    }
}

Важные правила

Правило 1: Один объект блокировки на один ресурс

private Object dataLock = new Object();
private Object cacheLock = new Object();

public void updateData() {
    synchronized(dataLock) { /* работа с data */ }
}

public void updateCache() {
    synchronized(cacheLock) { /* работа с cache */ }
}

Правило 2: Никогда не синхронизируйся на String или Integer

// Очень плохо!
synchronized("lock") { /* ... */ } // интернируются, разделяются между потоками
synchronized(Integer.valueOf(123)) { /* ... */ } // кэшируются!

// Правильно
synchronized(new Object()) { /* ... */ }

**Правило 3: Последовательность блокировок (Deadlock) **

// Опасно! Deadlock
Thread 1: synchronized(a) { synchronized(b) { } }
Thread 2: synchronized(b) { synchronized(a) { } }

// Правильно: всегда один и тот же порядок
Thread 1: synchronized(a) { synchronized(b) { } }
Thread 2: synchronized(a) { synchronized(b) { } }

Что происходит в скобках

synchronized(expression) {
    // expression должен быть Object
    // Java проверит, свободна ли блокировка на объект
    // Если занята: поток ждёт в очереди
    // Если свободна: поток берёт блокировку
    // Выход из блока: блокировка автоматически освобождается
}

Конкурентные коллекции (современный подход)

Вместо synchronized лучше использовать:

List<User> users = new CopyOnWriteArrayList<>();
Set<String> tags = Collections.newSetFromMap(new ConcurrentHashMap<>());
Queue<Task> tasks = new ConcurrentLinkedQueue<>();

Этим методам не нужны явные synchronized блоки.

Ответ: В скобках пишется объект, на котором устанавливается монитор (блокировка). Это может быть this, отдельный объект, класс (ClassName.class) или любой другой Object.