Когда горутина выполняет блокирующий системный вызов (например, чтение из сетевого сокета, в котором нет доступных данных), поток ОС (M), выполняющий этот системный вызов, блокируется в ядре.
-
Обработка планировщика: Чтобы предотвратить блокировку M от удержания своего P и, таким образом, предотвращение запуска других горутин, связанных с этим P, планировщик Go делает следующее: 1. Он обнаруживает, что M собирается заблокироваться при системном вызове. 2. Он отделяет P от блокирующего M. 3. Он находит или создает новый M и соединяет его с теперь свободным P. 4. Этот новый M может затем продолжить выполнение других исполняемых горутин из очереди выполнения P. 5. Когда исходный системный вызов M возвращается, он пытается получить свободный P, чтобы возобновить выполнение. Если доступного P нет, он помещает себя в список простаивающих M, ожидающих P.
-
Преимущество: Этот механизм гарантирует, что один блокирующий системный вызов не остановит все остальные горутины на этом логическом процессоре, что крайне важно для создания отзывчивых серверных служб, которые одновременно выполняют множество операций ввода-вывода.
Итог
Когда горутина выполняет блокирующий системный вызов (например, чтение из сетевого сокета, в котором нет доступных данных), поток ОС (M), выполняющий этот системный вызов, блокируется в ядре.