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

В каких случаях возникает deadlock в многопоточности

1.8 Middle🔥 151 комментариев
#Многопоточность

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

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

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

В каких случаях возникает deadlock в многопоточности

Deadlock (взаимная блокировка) — это ситуация, когда две или более потока остаются заблокированы навечно, ожидая друг друга. Это одна из самых опасных проблем в многопоточном программировании.

Условия возникновения Deadlock (четыре условия Кофмана)

Deadlock возникает только при одновременном выполнении всех четырёх условий:

  1. Mutual Exclusion (Взаимное исключение) — ресурс может быть занят только одним потоком
  2. Hold and Wait (Занимай и жди) — поток может удерживать ресурс и одновременно ждать другого
  3. No Preemption (Отсутствие вытеснения) — ресурс нельзя отобрать у потока насильно
  4. Circular Wait (Циклическое ожидание) — существует цикл потоков, каждый из которых ждёт ресурс, занимаемый следующим

Классический пример Deadlock

public class DeadlockExample {
    static class Account {
        int id;
        double balance;
        
        Account(int id, double balance) {
            this.id = id;
            this.balance = balance;
        }
    }
    
    static void transferMoney(Account from, Account to, double amount) {
        synchronized (from) {
            System.out.println(Thread.currentThread().getName() + " захватил " + from.id);
            
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            synchronized (to) {
                System.out.println(Thread.currentThread().getName() + " захватил " + to.id);
                from.balance -= amount;
                to.balance += amount;
            }
        }
    }
    
    public static void main(String[] args) {
        Account account1 = new Account(1, 1000);
        Account account2 = new Account(2, 2000);
        
        Thread t1 = new Thread(() -> transferMoney(account1, account2, 100));
        Thread t2 = new Thread(() -> transferMoney(account2, account1, 200));
        
        t1.start();
        t2.start();
    }
}

Другие примеры Deadlock

Пример 2: Несогласованный порядок блокировок

public class DeadlockWithObjects {
    Object lock1 = new Object();
    Object lock2 = new Object();
    
    public void method1() {
        synchronized (lock1) {
            synchronized (lock2) {
                System.out.println("Method 1");
            }
        }
    }
    
    public void method2() {
        synchronized (lock2) {
            synchronized (lock1) {
                System.out.println("Method 2");
            }
        }
    }
}

Способы избежать Deadlock

1. Всегда использовать один и тот же порядок блокировок:

static void transferMoneyFixed(Account from, Account to, double amount) {
    Account first = from.id < to.id ? from : to;
    Account second = from.id < to.id ? to : from;
    
    synchronized (first) {
        synchronized (second) {
            from.balance -= amount;
            to.balance += amount;
        }
    }
}

2. Использовать ReadWriteLock:

import java.util.concurrent.locks.*;

public class SafeAccount {
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    private double balance;
    
    public void transfer(double amount) {
        lock.writeLock().lock();
        try {
            balance -= amount;
        } finally {
            lock.writeLock().unlock();
        }
    }
}

3. Установить timeout на блокировку:

import java.util.concurrent.locks.*;

ReentrantLock lock = new ReentrantLock();

try {
    if (lock.tryLock(5, TimeUnit.SECONDS)) {
        try {
            // Критическая секция
        } finally {
            lock.unlock();
        }
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

Deadlock — одна из самых сложных проблем для отладки, поэтому лучше использовать проверенные паттерны синхронизации и high-level API.

В каких случаях возникает deadlock в многопоточности | PrepBro