Подтвердить что ты не робот

Является ли Go goroutine сопрограммой?

В предложении Google I/O 2012 Go Concurrency Шаблоны, Роб Пайк упоминает, что несколько горутов могут жить в одном потоке. Означает ли это, что они реализованы как сопрограммы? Если нет, то как они реализованы? Ссылки на исходный код будут приветствоваться.

4b9b3361

Ответ 1

Не совсем. Раздел часто задаваемых вопросов о Go Почему подпрограммы вместо потоков? объясняет:

Goroutines являются частью облегчения использования параллелизма. Идея, которая уже давно существует, состоит в том, чтобы мультиплексировать независимо выполняемые функции - сопрограммы - в набор потоков. Когда сопрограмма блокируется, например, путем вызова системного вызова блокировки, среда выполнения автоматически перемещает другие сопрограммы в том же потоке операционной системы в другой, работающий поток, чтобы они не были заблокированы. Программист не видит ничего из этого, в чем суть. Результат, который мы называем "подпрограммами", может быть очень дешевым: они имеют небольшие накладные расходы, помимо памяти для стека, которая составляет всего несколько килобайт.

Чтобы сделать стеки небольшими, во время выполнения Go используются изменяемые размеры стеков с изменяемыми размерами. Новоиспеченному горутину дается несколько килобайт, чего почти всегда достаточно. Когда это не так, во время выполнения увеличивается (и сокращается) память для автоматического хранения стека, что позволяет многим процедурам жить в скромном объеме памяти. Загрузка ЦП в среднем составляет около трех дешевых инструкций на вызов функции. Целесообразно создавать сотни тысяч подпрограмм в одном и том же адресном пространстве. Если бы подпрограммы были просто потоками, системные ресурсы были бы исчерпаны в гораздо меньшем количестве.

Ответ 2

IMO, сопрограмма подразумевает поддержку явных средств для передачи управления другой сопрограмме. То есть программист программирует сопрограмму таким образом, когда они решают, когда сопрограмма должна приостановить выполнение и передать ее управление другой сопрограмме (либо путем ее вызова, либо путем возврата/выхода (обычно называемого yielding)).

Go "goroutines" - это еще одно: они неявно передают управление в определенных неопределенных точках 1 которые происходят, когда goroutine собирается спать на некотором (внешнем) ресурсе, таком как завершение ввода/вывода, передача канала и т.д. Этот подход в сочетании с разделяющим состоянием через каналы позволяет программисту написать логику программы как набор последовательных легких процессов, которые устраняют проблему кода спагетти, общую для обоих подходов на основе команд и событий.

Что касается реализации, я думаю, что они очень похожи на (к сожалению, не слишком известную) "State Threads" library, просто довольно низкоуровневый (поскольку Go не полагается на libc или что-то вроде этого и говорит напрямую с ядром ОС) — вы можете прочитать вводный документ для библиотеки ST, где концепция достаточно хорошо объяснена.


1 Фактически эти точки менее детерминированы, чем команды сопрограмм, но более детерминированы, чем при действительных потоках ОС в превентивная многозадачность, где каждый поток может быть приостановлен ядром в любой момент времени и в потоке управления потоком.

Ответ 3

Если goroutine является надлежащей сопрограммой или просто что-то подобное, часто обсуждаются на https://groups.google.com/forum/?fromgroups=#!forum/golang-nuts. Некоторые люди могут спорить о таких тонкостях, но для большинства из них: goroutine является сопрограммой.

Посмотрите https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit чтобы понять, как работает планировщик.

Ответ 4

Goroutine - это отдельный "поток" выполнения. ИМО действительно не сравним с сопрограммой. В первом приближении, goroutines могут быть реализованы реальными потоками ОС. AFAIK, это было в случае ранних версий gccgo. Другое отличие состоит в том, что goroutines могут быть выгружены.

Текущие компиляторы Go реализуют goroutines как очень легкое, пользовательское пространство "threads". Одна особенная функция, например, зеленые потоки - это то, что goroutines могут переключаться на разные потоки ОС.

Я думаю, вы можете найти здесь некоторые связанные с этим биты: proc.c