Назад к вопросам
Middle
124
questionbank

В каких случаях может произойти дедлок?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

В Golang дедлок чаще всего возникает при работе с мьютексами и каналами.

Возможные случаи:

  • Циклическая зависимость мьютексов: Две или более горутины пытаются получить блокировку на мьютексы в разном порядке, создавая взаимоблокировку.

    // goroutine 1
    mu1.Lock()
    mu2.Lock() // ждет mu2, который занят goroutine 2
    
    // goroutine 2
    mu2.Lock()
    mu1.Lock() // ждет mu1, который занят goroutine 1
    
  • Блокирующая отправка в небуферизованный канал, который никто не читает: Горутина отправляет данные в канал, но нет другой горутины, готовой их принять.

    ch := make(chan int)
    ch <- 1 // блокируется навсегда, если нет получателя
    
  • Блокирующее чтение из канала, в который никто не пишет: Горутина пытается прочитать данные из канала, но никто не отправляет в него данные.

    ch := make(chan int)
    <-ch // блокируется навсегда, если нет отправителя
    
  • Использование одного и того же мьютекса в рекурсивной функции без RWMutex:

    var mu sync.Mutex
    
    func recursiveFunc() {
        mu.Lock() // попытка повторно заблокировать тот же мьютекс
        // ...
        // mu.Unlock() // никогда не будет достигнуто
    }
    
  • Отправка в закрытый канал или чтение из закрытого канала без проверки: Отправка в закрытый канал вызовет панику, чтение из закрытого канала вернет нулевое значение и false, но если не проверять второй возвращаемый параметр, можно некорректно обработать ситуацию и потенциально привести к дедлоку в другом месте.

  • Неправильное использование sync.WaitGroup: Например, вызов Done() раньше, чем было выполнено необходимое количество Add(), или вызов Wait() раньше, чем все горутины завершили свою работу.

Таблица с примерами:

Ситуация Механизм Пример
Циклическая зависимость мьютексов sync.Mutex Горутина A ждет B, Горутина B ждет A
Блокирующая отправка в канал Небуферизованный канал ch <- data без получателя
Блокирующее чтение из канала Канал <-ch без отправителя
Рекурсивное использование мьютекса sync.Mutex Повторная блокировка в той же горутине
Работа с закрытым каналом без проверки Канал Отправка в закрытый канал
Неправильное использование WaitGroup sync.WaitGroup Ошибки в логике Add/Done/Wait