Skip to content

Горутины

В этой теме мы разберем, что такое горутины, состояния и планировщик горутин, отложенные вызовы функций, а также рассмотрим панику и восстановление. Начнём!

Горутины

Современные ЦП часто имеют несколько ядер, а некоторые ядра ЦП поддерживают гиперпоточность. Современные процессоры могут одновременно обрабатывать несколько конвейеров команд. Чтобы в полной мере использовать возможности современных процессоров, нам необходимо выполнять конкурентное программирование при кодировании наших программ.

Конкурентные вычисления — это форма вычислений, при которой несколько вычислений выполняются в течение перекрывающихся периодов времени. На следующем изображении показаны два случая конкурентных вычислений. На изображении A и B представляют собой два отдельных вычисления. Второй случай также называется конкурентными вычислениями, то есть специальными одновременными вычислениями. В первом случае А и В параллельны только в течение небольшого промежутка времени.

Конкурентные вычисления могут происходить в программе, на компьютере или в сети. Мы говорим только о конкурентных вычислениях в рамках программы. Goroutine — это способ Go для создания конкурентных вычислений в программировании Go.

Горутины также часто называют зелеными потоками. Зеленые потоки поддерживаются и планируются средой выполнения языка, а не операционными системами. Стоимость потребления памяти и переключения контекста для горутины намного меньше, чем для потока ОС. Размер горутины составляет от 2 кб, размер стэка горутины меняется динамически. Таким образом, для программы Go не проблема одновременно поддерживать десятки тысяч горутин, если достаточно системной памяти.

Go не поддерживает создание системных потоков в пользовательском коде. Таким образом, использование горутин — единственный способ выполнять (в рамках программы) параллельное программирование в Go.

Каждая программа Go начинается только с одной горутины, мы называем ее основной горутиной. Горутина может создавать новые горутины. В Go очень легко создать новую горутину, просто используя ключевое слово go, за которым следует вызов функции. Затем вызов функции будет выполнен во вновь созданной горутине. Вновь созданная горутина завершится вместе с выходом из вызванной функции.

Все значения результата вызова функции горутины (если вызываемая функция возвращает значения) должны быть отброшены в операторе вызова функции. Ниже приведен пример создания двух новых горутин в основной горутине. В примере time.Duration это пользовательский тип, определенный в time стандартном пакете. Его базовым типом является встроенный тип int64.

Пришло время поработать с кодом!

Довольно легко, верно? Мы занимаемся конкурентным программированием прямо сейчас! Вышеупомянутая программа может иметь три созданные пользователем горутины, работающие одновременно на пике во время выполнения. Давай запустим его. Один из возможных выходных результатов.

Когда основная горутина завершается, вся программа также завершается, даже если есть какие-то другие горутины, которые еще не завершились.

В отличие от предыдущих примеров, эта программа использует Println функцию из log стандартного пакета вместо соответствующей функции из fmt стандартного пакета. Причина в том, что функции печати в log стандартном пакете синхронизированы, поэтому тексты, напечатанные двумя горутинами, не будут перепутаны в одну строку, хотя вероятность того, что напечатанные тексты будут перепутаны с использованием функций печати в fmt стандартном пакете, очень мала для этой конкретной программы.