“协同程序”和“线程”之间有什么区别
首先阅读:并发与并行-有什么区别
并发是任务的分离,以提供交错的
处决并行性是同时执行多个
为了提高工作速度-https://github.com/servo/servo/wiki/Design
简短回答:对于线程,操作系统根据其调度程序(操作系统内核中的一种算法)抢先切换运行的线程。对于协同程序,程序员和编程语言决定何时切换协同程序;换句话说,任务是通过在设定点暂停和恢复函数来协同多任务的,通常(但不一定)在单个线程内
详细回答:与由操作系统预先调度的线程不同,协同路由切换是协作的,这意味着程序员(可能还有编程语言及其运行时)控制切换何时发生
与先发制人的线程不同,协同路由开关是
协作(程序员控制何时发生切换)。这个
coroutine开关中不涉及内核。
—http://www.boost.org/doc/libs/1_55_0/libs/coroutine/doc/html/coroutine/overview.html
支持本机线程的语言可以在操作系统的线程(内核线程)上执行其线程(用户线程)。每个进程至少有一个内核线程。内核线程与进程类似,只是它们在自己的进程中与该进程中的所有其他线程共享内存空间。进程“拥有”所有分配的资源,如内存、文件句柄、套接字、设备句柄等,这些资源都在其内核线程之间共享
操作系统调度程序是内核的一部分,在一定时间内(在单处理器机器上)运行每个线程。调度程序为每个线程分配时间(timeslicing),如果该线程在该时间内未完成,调度程序将抢占该线程(中断该线程并切换到另一个线程)。多个线程可以在多处理器机器上并行运行,因为每个线程可以(但不一定必须)调度到单独的处理器上
在单处理器机器上,线程是分时间片的,并且可以快速抢占(在Linux上,默认时间片为100ms),这使得线程是并发的。然而,它们不能并行(同时)运行,因为单核处理器一次只能运行一件事情
协同程序和/或生成器可用于实现协同功能。它们不是在内核线程上运行并由操作系统调度,而是在单个线程中运行,直到它们屈服或完成,屈服于程序员确定的其他函数。带有生成器的语言(如Python和ECMAScript 6)可用于构建协同路由。Async/await(见于C#、Python、ECMAscript 7、Rust)是构建在生成函数之上的抽象,生成未来/承诺
在某些上下文中,协程可能指堆栈函数,而生成器可能指无堆栈函数
光纤、轻量级线程和绿色线程是协同程序或类似协同程序的其他名称。它们有时看起来(通常是有意的)更像编程语言中的操作系统线程,但它们不像真正的线程那样并行运行,而是像协同程序一样工作。(根据语言或实现,这些概念之间可能存在更具体的技术特殊性或差异。)
例如,Java有“绿色线程””;这些线程是由Java虚拟机(JVM)调度的,而不是在底层操作系统的内核线程上本地调度的。它们没有并行运行,也没有利用多个处理器/内核——因为这需要一个本机线程!因为它们不是由操作系统调度的,所以它们更像是协同路由而不是内核线程。在Java 1.2引入本机线程之前,Java一直使用绿色线程
线程消耗资源。在JVM中,每个线程都有自己的堆栈,通常为1MB大小。64k是JVM中每个线程允许的最小堆栈空间量。可以在JVM的命令行上配置线程堆栈大小。不管名称如何,线程都不是免费的,因为它们使用的资源包括每个线程需要自己的堆栈、线程本地存储(如果有)以及线程调度/上下文切换/CPU缓存失效的成本。这就是为什么协同路由在性能关键、高度并发的应用程序中变得流行的部分原因
Mac OS只允许一个进程分配大约2000个线程,Linux为每个线程分配8MB的堆栈,并且只允许物理RAM中容纳的线程数量
因此,线程是最重的重量(就内存使用和上下文切换时间而言),然后是协同路由,最后是生成器是最轻的重量