← Назад к вопросам
Что пишется в круглых скобках вместе с 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.