当前位置:  开发笔记 > 编程语言 > 正文

"coroutine"和"thread"之间的区别?

如何解决《"coroutine"和"thread"之间的区别?》经验,为你挑选了5个好方法。

"coroutine"和"thread"之间有什么区别?



1> llambda..:

首先阅读: 并发与并行 - 有什么区别?

并发是分离任务以提供交叉执行.并行性是指同时执行多项工作以提高速度.- https://github.com/servo/servo/wiki/Design

简答:使用线程,操作系统根据其调度程序(操作系统内核中的算法)预先切换运行线程.使用协同程序,程序员和编程语言决定何时切换协同程序; 换句话说,通过在设定点暂停和恢复功能来协同地执行任务,通常(但不一定)在单个线程内.

答案很长:与操作系统预先安排的线程相比,协程开关是协作的,这意味着程序员(可能还有编程语言及其运行时)控制何时发生切换.

与先发制人的线程相比,协程开关是协作的(程序员控制何时会发生切换).内核不参与协程开关.- http://www.boost.org/doc/libs/1_55_0/libs/coroutine/doc/html/coroutine/overview.html

支持本机线程的语言可以将其线程(用户线程)执行到操作系统的线程(内核线程)上.每个进程至少有一个内核线程.内核线程就像进程一样,除了它们在拥有进程中与该进程中的所有其他线程共享内存空间.进程"拥有"其所有已分配的资源,如内存,文件句柄,套接字,设备句柄等,这些资源都在其内核线程之间共享.

操作系统调度程序是运行每个线程一段时间(在单个处理器机器上)的内核的一部分.调度程序为每个线程分配时间(时间分隔),如果线程未在该时间内完成,则调度程序会抢占它(中断它并切换到另一个线程).多个线程可以在多处理器机器上并行运行,因为每个线程可以(但不一定必须)调度到单独的处理器上.

在单处理器计算机上,线程被快速切换并被抢占(在其间切换)(在Linux上,默认时间片为100毫秒),这使它们并发.但是,它们不能并行(同时)运行,因为单核处理器一次只能运行一件事.

协程和/或生成器可用于实现协作功能.它们不是在内核线程上运行并由操作系统调度,而是在单个线程中运行,直到它们产生或完成,从而产生由程序员确定的其他函数.生成器的语言,如Python和ECMAScript 6,可用于构建协同程序.Async/await(见于C#,Python,ECMAscript 7,Rust)是一个基于生成函数的抽象,它产生了期货/承诺.

在某些情况下,协同程序可能指的是堆栈函数,而生成器可能指的是无堆栈函数.

纤维,轻量级线程绿色线程是协同程序或类似协程式事物的其他名称.它们有时看起来(通常是故意的)更像是编程语言中的操作系统线程,但它们并不像真正的线程那样并行运行,而是像协程一样工作.(这些概念可能有更具体的技术特点或差异,具体取决于语言或实施.)

例如,Java有" 绿线 "; 这些是由Java虚拟机(JVM)调度的线程,而不是本机在底层操作系统的内核线程上调度的线程.这些并不是并行运行或利用多个处理器/内核 - 因为这需要本机线程!由于它们不是由操作系统安排的,因此它们更像是协程而不是内核线程.绿色线程是Java在将原生线程引入Java 1.2之前使用的.

线程消耗资源.在JVM中,每个线程都有自己的堆栈,通常为1MB.64k是JVM中每个线程允许的最小堆栈空间量.可以在JVM的命令行上配置线程堆栈大小.尽管名称,线程不是免费的,因为它们的使用资源,如每个线程需要自己的堆栈,线程本地存储(如果有的话),以及线程调度/上下文切换/ CPU缓存失效的成本.这是协同程序在性能关键,高度并发应用程序中变得流行的部分原因.

Mac OS只允许进程分配大约2000个线程,Linux每个线程分配8MB堆栈,并且只允许适合物理RAM的线程数量.

因此,线程是最重的(在内存使用和上下文切换时间方面),然后是协同程序,最后生成器是最轻的权重.



2> Alex Martell..:

协同程序是一种顺序处理形式:只有一个在任何给定时间执行(就像子程序AKA程序AKA功能一样 - 它们只是让接力棒更加流畅地传递).

线程(至少在概念上)是并发处理的形式:多个线程可以在任何给定时间执行.(传统上,在单CPU,单核机器上,通过操作系统的一些帮助来模拟并发性 - 如今,由于许多机器是多CPU和/或多核,因此线程事实上将同时执行,不只是"概念上").



3> Martin Konec..:

大约7年后,但这里的答案缺少一些关于协同例程与线程的背景.为什么协程最近会受到如此多的关注,何时我会使用它们与线程相比?

首先,如果协同程序同时运行(从不并行),为什么有人会更喜欢它们而不是线程?

答案是协同程序可以提供非常高的并发性,而且开销很小.通常在线程环境中,在浪费开销之前,最多有30-50个线程实际调度这些线程(通过系统调度程序)会显着缩短线程实际执行有用工作的时间.

好吧,对于线程,你可以有并行性,但不是太多的并行性,是不是仍然比在单个线程中运行的协同例程更好?不一定.记住,协同例程仍然可以在没有调度程序开销的情况下进行并发 - 它只是管理上下文切换本身.

例如,如果你有一个例程做一些工作,并且它执行一个操作,你知道会阻塞一段时间(即一个网络请求),通过一个协同例程,你可以立即切换到另一个例程,而不需要包含系统调度程序的开销这个决定 - 是的,程序员必须指定协同例程何时可以切换.

由于许多例程正在进行非常少量的工作并且彼此之间自愿切换,因此您已达到了调度程序无法实现的效率水平.你现在可以拥有数千个协同程序,而不是数十个线程.

因为您的例程现在在彼此之间切换预定点,您现在也可以避免锁定共享数据结构(因为您永远不会告诉您的代码在关键部分中间切换到另一个协程)

另一个好处是内存使用量低得多.使用线程模型,每个线程都需要分配自己的堆栈,因此您的内存使用量会随着线程数的增加而线性增长.使用协同例程,您拥有的例程数量与您的内存使用量没有直接关系.

最后,协同例程正在受到很多关注,因为在某些编程语言(例如Python)中,您的线程无论如何都无法并行运行 - 它们像协程一样并发运行,但没有低内存和免费调度开销.


当我们遇到阻塞操作时,如何在协同程序中切换到另一个任务?

4> Peter Rowell..:

总之一句话:先发制人.协同程序就像玩杂耍者一样,不断向对方传递一个经过良好排练的点.线程(真正的线程)几乎可以在任何点上中断,然后再恢复.当然,这带来了各种资源冲突问题,因此Python臭名昭着的GIL - Global Interpreter Lock.

许多线程实现实际上更像是协同程序.



5> Thomas Bonin..:

这取决于您使用的语言.例如在Lua中它们是相同的(调用coroutine的变量类型thread).

通常虽然协同程序实现自愿屈服,但程序员决定在哪里yield,即控制另一个例程.

相反,线程由操作系统自动管理(停止和启动),甚至可以在多核CPU上同时运行.

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有