Это совершенно не та же проблема, что и в потоках.
Все сопрограммы работают в одном потоке, в сопрограммах нет проблем с многопоточностью.
Но проблема заключается впереключатель сопрограмм.Когда вы используете await asyncio.sleep(1)
, это ожидание вызовет переключение контекста с одной сопрограммы на другую.
Давайте возьмем две сопрограммы в качестве примера: C1
и C2
.Итак, сначала есть очередь выполнения для этих двух сопрограмм: Q{C1, C2}
.Затем C1
запускается для выполнения, и без await
переключателя нет, поэтому C1
будет выполнен полностью.Затем для выполнения запускается C2
.
Таким образом, порядок выполнения - C1 -> C2
.Это абсолютно линейно.
Но когда есть await
, это вызовет переключение.Это означает, что C1
будет остановлен и вставлен в конец очереди.Тогда C2
будет вытолкнут для выполнения.При этом C2
также будет остановлен на этой строке и вставлен в конец очереди.Далее C1
будет снова выведено и выполнено полностью.
Таким образом, порядок выполнения будет C1(before await) -> C2(before await) -> C1(the rest) -> C2(the rest)
.
Очевидно, что все ваши сопрограммы будут остановлены после проверки val
.Что является основной проблемой.Это не проблема гонок параллелизма, но проблема реального понимания того, как await
повлияет на вашу программу.