Каков алгоритм, стоящий за тем, что все goroutines Golang спят - тупик! - PullRequest
0 голосов
/ 13 мая 2018

Сохраняет ли среда выполнения ориентированный граф, представляющий, какую программу где-то ждет? Если да, не могли бы вы указать мне соответствующее место в исходном коде?

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

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Вы можете проверить исходный код Go и легко узнать: это происходит в этой функции , которая вызывается в различных местах, где программа может перейти в состояние тупика.

Соответствующая часть заключается в том, что среда выполнения получает количество открытых потоков ОС и проверяет, сколько из них фактически выполняет код. Есть еще несколько проверок, но это в основном все. Всякий раз, когда вы запускаете операцию блокировки - например, блокировку мьютекса, когда он уже был заблокирован в другом месте, или получение из пустого канала - планировщик будет пытаться заставить поток выполнять работу другой процедуры. Если ни один не может быть найден, он переходит в состояние ожидания.

Обычно планировщик всегда пытается найти код, ожидающий запуска. Если ничего не найдено, то это тупиковая ситуация.

Это, конечно, исключает случаи, когда запускаются программы time.Sleep, которые хотя и "простаивают", но есть поток, активно проверяющий, когда они готовы к запуску. Другими словами, они не зависят от других частей программы, чтобы снова стать «работоспособными» (например, в случае мьютексов).

0 голосов
/ 14 мая 2018

Коротко: Планировщик времени выполнения, отвечающий за распределение времени выполнения потоков ОС между подпрограммами, понимает, что все подпрограммы ждут вечно или ожидают в других подпрограммах, и завершает взаимоблокировку.

Представьте себе сценарий, в котором программа А извлекает страницы из Интернета, отправляя их по каналу С на маршрут Б. В программу А нечего делать, пока программа Б не отправит на канал С, поэтому программа А спит, ожидая вызова программы А. B блокируется в ожидании завершения системного вызова (HTTP-запроса), поэтому подпрограмма B не ожидает других подпрограмм. Теперь, если вы вставите какую-либо операцию, которая заставит g-подпрограмму B ждать другие goroutines (например, получение из канала D), g-подпрограмма B будет переведена в спящий режим, и, поскольку все остальные goroutines (в действительности только goroutine A) уже спят, мы завершаем тупик .

Long: чтение Go планировщик .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...