Что происходит с горутиной, работающей с синхронными системными вызовами

«Что происходит с горутиной, работающей с синхронными системными вызовами» — вопрос из категории Golang, который задают на 23% собеседований Golang Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Горутина, выполняющая синхронный системный вызов (например, файловый I/O или сетевой запрос без netpoll), блокируется на время выполнения этого вызова. В этот момент планировщик Go (scheduler) может переключиться на другую горутину в том же потоке (M), пока системный вызов не завершится.

Пример:

file, err := os.Open("example.txt") // Синхронный вызов
if err != nil {
    log.Fatal(err)
}
defer file.Close()

Нюансы:

  1. Если все потоки (M) заблокированы на системных вызовах, планировщик может создать новый поток (до GOMAXPROCS).
  2. Для сетевых операций Go использует асинхронный ввод-вывод (через netpoll), поэтому горутины не блокируются.
  3. Долгие синхронные вызовы (например, тяжелые вычисления в CGO) могут "заморозить" планировщик.