进程,线程,绿色线程,原线程,纤维,协程:有什么区别?
我正在阅读并发。 我的脑海中有一些混淆相似的定义。 即:
- stream程
- 主题
- “绿色线索”
- Protothreads
- 纤维
- 协同程序
- Go语言中的“Goroutines”
我的印象是,区别在于:(1)是真正的并行还是多路复用; (2)是否在CPU,操作系统或程序中进行pipe理; 和(3..5)其他一些我无法识别的东西。
对于这些并行性方法之间的差异,有没有一个简洁而明确的指导?
好吧,我会尽我所能。 有各种各样的警告,但我会尽我所能,让我理解这些术语和参考近似我给定义的东西。
- 过程 :OSpipe理(可能)真正并发,至less在适当的硬件支持的情况下。 存在于自己的地址空间内。
- 线程 :操作系统pipe理,与父代和所有其他线程在相同的地址空间内。 可能真正的并发,多任务是先发制人。
- 绿色线程 :这是与线程相同概念的用户空间投影,但不是由OSpipe理的。 可能不是真正的并发,除非可能有多个工作线程或进程同时给予CPU时间,所以最好将其视为交错或多路复用。
- Protothreads :我无法从这些中挑出一个定义。 我认为它们是交织的和程序pipe理的,但不要听我的话。 我的感觉是,它们本质上是一种相同types的“绿色线程”模型的特定于应用程序的实现,并对应用程序域进行了适当的修改。
- 光纤 :OSpipe理。 完全是线程,除了合作多任务,因此不是真正的并发。
- 协程 :确切地说是纤维,除非操作系统pipe理。
- Goroutines :他们声称与其他任何东西都不一样,但它们似乎完全是绿色的线程,就像在单个地址空间中进行进程pipe理并复用到系统线程中一样。 也许有更多的知识的人可以切断营销材料。
同样值得注意的是,在过程演算的意义上,“过程”一词的并发理论还有其他的理解。 这个定义与上面的定义是正交的,但是我只是觉得值得一提,所以如果你看到某个地方的stream程被使用了,那么就不会出现混淆。
另外,请注意并行和并发之间的区别。 你可能在你的问题中使用前者,我认为你的意思是后者。
我主要赞同Gian的回答,但我对一些并发原语有不同的解释。 请注意,这些术语通常由不同的作者使用不一致。 这些是我最喜欢的定义(希望不要离现代共识太远)。
- 处理:
- OSpipe理
- 每个都有自己的虚拟地址空间
- 可以被系统中断(抢占)以允许另一个进程运行
- 可以在不同处理器上与其他进程并行运行
- 进程的内存开销很大(包括虚拟内存表,打开文件句柄等)
- 在进程之间创build和上下文切换的时间开销相对较高
- 主题:
- OSpipe理
- 在某个特定的过程中,每个“被包含”
- 同一进程中的所有线程共享相同的虚拟地址空间
- 可以被系统中断以允许另一个线程运行
- 可以与不同处理器上的其他线程并行运行
- 与线程相关的内存和时间开销比进程小,但仍然不平凡
- (例如,通常上下文切换涉及进入内核并调用系统调度程序。)
- 合作线程:
- 可能或不可以由操作系统pipe理
- 在某个特定的过程中,每个“被包含”
- 在一些实现中,每个在某个特定的OS线程内被“包含”
- 不能被系统中断以允许合作伙伴运行
- (当然,包含进程/线程仍然可以中断)
- 必须调用特殊的yield基元以允许对等协作线程运行
- 一般不能与合作伙伴同步运行
- (尽pipe有些人认为这是可能的: http : //ocm.dreamhosters.com/ 。)
- 合作主题主题中有很多不同的变体:
- 纤维
- 绿色的线程
- Protothreads
- 用户级线程(用户级线程可以是可中断/抢占的,但是这是一个相对不寻常的组合)
- 协作线程的一些实现使用诸如分割/分段堆栈之类的技术,或者甚至单独堆分配每个调用帧以减less与为堆栈预分配大块内存相关联的内存开销
- 根据实现的不同,调用阻塞系统调用(如从networking读取或hibernate)将导致整组协作线程阻塞或隐式地导致调用线程产生
- 协同程序:
- 有些人或多或less同意使用“协同程序”和“协作线程”
- 我不喜欢这种用法
- 一些协程实现实际上是“浅”的协作线程; 收益率只能由“协同进入程序”调用
- 浅(或半协程)版本比线程更容易实现,因为每个协程不需要一个完整的堆栈(只有一个入口过程的框架)
- 通常,协同程序框架具有屈服原语,要求调用者明确指出哪个协程控制应该传递给哪个协程
- 有些人或多或less同意使用“协同程序”和“协作线程”
- 发电机:
- 受限(浅)协程
- yield只能将控制权返回给调用生成器的任何代码
- 够程:
- 一个奇怪的混合的合作和操作系统线程
- 不能被打断(像合作的线程)
- 可以在OS线程的语言运行时pipe理的池上并行运行
- 事件处理程序:
- 由事件调度程序响应某些操作而调用的过程/方法
- 用户界面编程非常stream行
- 几乎不需要语言/系统支持; 可以在图书馆实施
- 一次只能运行一个事件处理程序; 调度员必须等待处理程序完成(返回)才能开始下一个
- 使同步相对简单; 不同的处理程序执行不会在时间上重叠
- 使用事件处理程序执行复杂的任务往往会导致“反向控制stream”/“堆栈翻录”
- 任务:
- 经理向工作人员分配的工作单位
- 工人可以是线程,进程或机器
- 当然,任务库使用的这种工作人员对于如何执行任务有着重大的影响
- 在这个不一致和混淆使用的术语列表中,“任务”取冠。 特别是在embedded式系统社区中,“任务”有时用来表示“进程”,“线程”或“事件处理程序”(通常称为“中断服务程序”)。 它有时也被用于一般/非正式地指代任何种类的计算单位。
我无法阻止自己的发泄:我不喜欢使用“真并发”这个词来表示“处理器并行性”。 这很常见,但我认为这会导致很多混乱。
对于大多数应用程序,我认为基于任务的框架最适合并行化。 大部分受欢迎的(Intel的TBB,苹果的GCD,微软的TPL&PPL)使用线程作为工作者。 我希望有一些很好的替代scheme使用过程,但我不知道任何。
如果您对并发感兴趣(而不是处理器并行),事件处理程序是最安全的方法。 合作的线程是一个有趣的select,但有点狂野西部。 如果您关心软件的可靠性和健壮性,请不要使用线程进行并发。
Protothreads只是一个开关盒的实现,它像状态机一样工作,但使软件的实现变得更简单。 它基于在一个case标签之前保存一个int值的思想,然后返回,然后通过回读该variables并使用开关来确定继续的位置,从而返回到该case之后的点。 所以protothread是一个状态机的顺序执行。
在实现顺序状态机时,Protothreads非常棒。 Protothreads根本不是真正的线程,而是一种语法抽象,使编写一个必须顺序切换状态(从一个到下一个等等)的交换机/机箱状态机更容易。
我已经使用protothreads来实现asynchronousio: http ://martinschroder.se/asynchronous-io-using-protothreads/