Разница между "сопрограмма" и "нить"?

каковы различия между "сопрограмма" и "нить"?

5 ответов


Coroutines-это форма последовательной обработки: только один выполняется в любой момент времени (так же, как подпрограммы AKA процедуры AKA функции-они просто передают эстафету друг другу более плавно).

потоки (по крайней мере, концептуально) форма параллельной обработки: несколько потоков могут выполняться в любой момент времени. (Традиционно, на однопроцессорных, одноядерных машинах, этот параллелизм моделировался с некоторой помощью ОС-в настоящее время, так как так много машин являются мульти-CPU и / или многоядерными, потоки будут де-факто выполняйте одновременно, а не только"концептуально").


сначала прочитал: параллелизм против параллелизма-в чем разница?

параллелизм-это разделение задач для обеспечения чередования исполнение. Параллельность-это одновременное выполнение нескольких части работы для увеличения скорости. -https://github.com/servo/servo/wiki/Design

короткий ответ: с потоками операционная система переключает запущенные потоки упреждающе в соответствии с его планировщиком, который является алгоритмом в ядре операционной системы. С помощью сопроцессоров программист и язык программирования определяют, когда переключать сопроцессоры; другими словами, задачи совместно многозадачны, приостанавливая и возобновляя функции в заданных точках, как правило (но не обязательно) в пределах одного потока.

ответ: в отличие от потоков, которые предварительно запланированы операционной системой, переключатели coroutine кооперативный, то есть программист (и, возможно, язык программирования и его среда выполнения) контролирует, когда произойдет переключение.

в отличие от потоков, которые являются упреждающими, переключатели coroutine кооператив (программист контролирует, когда произойдет переключение). Этот ядро не участвует в переключателях coroutine. -http://www.boost.org/doc/libs/1_55_0/libs/coroutine/doc/html/coroutine/overview.html

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

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

на одной процессорной машине потоки timesliced и preempted (переключаются между) быстро (в Linux timeslice по умолчанию составляет 100 мс), что делает их параллельными. Однако их нельзя запускать параллельно (одновременно), так как одноядерный процессор может запускать только одну вещь за раз.

Coroutines и/или генераторы может использоваться для реализации совместных функций. Вместо запуска в потоках ядра и по расписанию операционная система, они работают в одном потоке, пока они не уступят или не закончат, уступая другим функциям, определенным программистом. Языки с генераторы, такие как Python и ECMAScript 6, могут использоваться для создания сопрограмм. Async / await (см. В C#, Python, ECMAscript 7, Rust) - это абстракция, построенная поверх функций генератора, которые дают фьючерсы/обещания.

в некоторых случаях coroutines may сослаться на stackful функции пока генераторы может ссылаться на stackless функции.

волокнами, легкие потоки и зеленые нити другие названия для сопрограмм или сопрограмма-как вещи. Иногда они могут выглядеть (как правило, специально) больше как потоки операционной системы на языке программирования, но они не работают параллельно, как реальные потоки, а работают как сопрограммы. (Могут быть более конкретные технические особенности или различия среди этих понятий в зависимости от языка или реализации.)

например, Java имел "зеленые нити"; это были потоки, которые были запланированы виртуальной машиной Java (JVM) вместо изначально на потоках ядра базовой операционной системы. Они не запускались параллельно или не использовали несколько процессоров/ядер-так как для этого потребовался бы собственный поток! Поскольку они не были запланированы ОС, они больше походили на сопрограммы, чем потоки ядра. Зеленые потоки-это то, что Java использовала, пока собственные потоки не были введены в Java 1.2.

потоки потребляют ресурсы. В JVM каждый поток имеет свой собственный стек, обычно размером 1 МБ. 64k-наименьшее количество пространства стека, разрешенное для каждого потока в JVM. Размер стека потоков можно настроить в командной строке для JVM. Несмотря на название, потоки не являются бесплатными из-за их использования ресурсов, таких как каждый поток, нуждающийся в собственном стеке, локальном хранилище потоков (если таковое имеется) и стоимости потока планирование / переключение контекста / недействительность кэша процессора. Это одна из причин, почему coroutines стали популярными для критически важных приложений с высокой производительностью.

Mac OS только позволит процессу выделить около 2000 потоков, а Linux выделяет 8 МБ стека на поток и позволит только столько потоков, которые будут соответствовать физической ОЗУ.

таким образом, потоки в тяжелом весе (в плане использования памяти и переключения контекста), то сопрограммы, и наконец, генераторы имеют самый легкий вес.


около 7 лет спустя, но ответы здесь не хватает некоторого контекста в подпрограммах против потоков. Почему coroutines получение так много внимания в последнее время, и когда я буду использовать их по сравнению с темы?

прежде всего, если coroutines run по совместительству (никогда в параллельно), почему кто-то предпочел бы их потокам?

ответ заключается в том, что coroutines может предоставить очень высокий уровень параллелизм С очень мало накладных. Как правило, в потоковой среде у вас есть не более 30-50 потоков до того, как количество потраченных впустую накладных расходов фактически планирует эти потоки (планировщиком системы) значительно сокращает время, в течение которого потоки фактически выполняют полезную работу.

хорошо, поэтому с потоками вы можете иметь параллелизм, но не слишком много параллелизма, разве это не лучше, чем совместная процедура, выполняемая в одном потоке? Что ж необязательно. Помните, что co-routine все еще может выполнять параллелизм без накладных расходов планировщика - он просто управляет самим переключением контекста.

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

с большим количеством процедур, выполняющих очень маленькие биты работы и добровольно переключающихся между собой, вы достигли уровня эффективности, на который не может надеяться ни один планировщик. Теперь вы можете иметь тысячи сопрограммы работают вместе, в отличие от десятков потоков.

потому что ваши процедуры теперь переключаются между собой заранее определенные точки вы можете теперь также избежать блокировки на общих структурах данных (потому что вы никогда скажите вашему коду переключиться на другую корутину в середине критического раздела)

Другим преимуществом является гораздо меньшее использование памяти. С помощью модели threaded каждый поток должен выделять свой собственный стек,и поэтому использование вашей памяти линейно растет с количеством потоков. С помощью подпрограмм количество подпрограмм, которые у вас есть, не имеет прямой связи с использованием вашей памяти.

и, наконец, совместные процедуры получают большое внимание, потому что в некоторых языки программирования (например, Python) ваш потоки не могут работать параллельно в любом случае - они работать одновременно как сопрограммы, но без нехватки памяти и свободное планирование затрат.


одним словом: упреждение. Акт сопрограммы как жонглеры, которые держат передавая друг другу хорошо отрепетированный очков. Потоки (true threads) могут быть прерваны практически в любой точке, а затем возобновлены позже. Конечно, это приносит с собой всевозможные проблемы конфликта ресурсов, поэтому печально известная блокировка интерпретатора Gil - Global Python.

многие реализации потоков на самом деле больше похожи на coroutines.


Это зависит от языка, который вы используете. Например в Lua Это одно и то же (тип переменной корутины называется thread).

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

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