Junior
62
questionbank

Что такое дедлок при работе с goroutine?

Получайте ответы на вопросы в реальном времени с Sobes Copilot
Ответ от нейросети sobes.tech

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

Примеры дедлока:

  1. Блокировка мьютексов в разном порядке:

    go

    Goroutine1 захватила mu1 и ждет mu2. Goroutine2 захватила mu2 и ждет mu1. Обе горутины заблокированы.

  2. Отправка в небуферизованный канал без получателя:

    go

    Отправка в небуферизованный канал блокируется до тех пор, пока другая горутина не начнет читать из него. Если получателя нет, происходит дедлок.

  3. Чтение из канала без отправителя (после закрытия или пустой буферизованный):

    go

    Чтение из закрытого непустого канала завершится успешно. Чтение из закрытого и пустого канала или из открытого, но пустого небуферизованного канала без отправителя приведет к блокировке.

Golang-рантайм может обнаружить определенные типы дедлоков (например, когда все заблокированные горутины ожидают получения или отправки единственной горутины), и в таком случае программа аварийно завершится с сообщением "fatal error: all goroutines are asleep - deadlock!". Однако, не все дедлоки могут быть автоматически обнаружены.

Для предотвращения дедлоков важно:

  • Соблюдать consistent порядок захвата мьютексов.
  • Убедиться, что для каждой отправки в небуферизованный канал есть соответствующее чтение, и наоборот.
  • При работе с каналами использовать select с default веткой или тайм-аутами при необходимости.
  • Аккуратно управлять временем жизни горутин и закрытием каналов.