线程和纤程有什么区别?我从Ruby中听说过纤程,并且我也听说其他语言中也有纤程的存在,请有人简单地解释一下线程和纤程之间的区别。
线程是操作系统调度的基本单位,它管理着程序执行的流程。纤程则是在用户空间实现协程的一种方式,它可以在单个线程内模拟多个执行流程。纤程在某些情况下比线程更加轻量级,因为它们不需要进行上下文切换和内核态和用户态之间的转换。线程和纤程有什么区别?我从Ruby中听说过纤程,并且我也听说其他语言中也有纤程的存在,请有人简单地解释一下线程和纤程之间的区别。
线程是操作系统调度的基本单位,它管理着程序执行的流程。纤程则是在用户空间实现协程的一种方式,它可以在单个线程内模拟多个执行流程。纤程在某些情况下比线程更加轻量级,因为它们不需要进行上下文切换和内核态和用户态之间的转换。线程使用抢占式调度,而纤程使用合作式调度。
使用线程时,控制流可以在任何时刻被中断,并且另一个线程可以接管。使用多个处理器时,您可以同时运行多个线程(同时多线程或SMT)。因此,您必须非常小心地处理并发数据访问,并使用互斥体、信号量、条件变量等来保护数据。这通常很棘手。
使用纤程时,只有在您告诉它切换时,控制才会转移,通常是使用类似于yield()
的函数调用。这使得并发数据访问更加容易,因为您不必担心数据结构或互斥体的原子性。只要您不进行切换,就不会面临被抢占并且有另一个纤程尝试读取或修改您正在处理的数据的危险。结果,如果您的纤程进入无限循环,没有其他纤程可以运行,因为您没有切换。
您还可以混合使用线程和纤程,这会导致两者都面临的问题。虽然不建议这样做,但如果小心操作,有时可能是正确的选择。
首先,建议阅读进程和线程之间的区别,作为背景资料。
一旦您阅读了它,就很容易理解了。线程可以在内核中、用户空间中实现,也可以混合使用。纤程(Fibers)基本上是在用户空间实现的线程。
在《现代操作系统》的第11.4节"Windows Vista中的进程和线程"中,Tanenbaum评论道:
可用处理器,甚至只有一个处理器。每个线程可以运行一组特定的纤维,建立了线程和纤维之间的一对多关系,简化了同步。即使如此,纤维仍然存在许多困难。大多数Win32库完全不知道纤维,试图将纤维用作线程的应用程序会遇到各种失败。内核没有纤维的知识,当纤维进入内核时,它正在执行的线程可能会阻塞,并且内核将在处理器上调度任意线程,使其无法运行其他纤维。出于这些原因,除非从其他系统移植需要纤维提供的功能代码,否则很少使用纤维。虽然纤程是合作调度的,但如果有多个线程调度纤程,则需要进行大量的仔细同步,以确保纤程不会相互干扰。为了简化线程和纤程之间的交互,通常只需要创建与处理器数量相同的线程,并将线程关联到每个独立的一组处理器上运行。
用户模式调度(UMS)是应用程序可以使用的轻量级机制,用于调度其自己的线程。应用程序可以在用户模式下在 UMS 线程之间切换,而不涉及系统调度程序,并且如果 UMS 线程在内核中阻塞,则可以重新控制处理器。UMS 线程与纤程的区别在于,每个 UMS 线程都具有自己的线程上下文,而不是共享单个线程的线程上下文。在用户模式下切换线程的能力使 UMS 比线程池更有效,用于管理需要很少的系统调用且持续时间短的大量工作项。
有关线程、纤程和 UMS 的更多信息,请观看 Dave Probert:Windows 7 内部-用户模式调度程序(UMS)。
线程通常依赖内核中断线程,以便它或另一个线程可以运行(更为人所知的是抢占式多任务处理),而纤程使用协作式多任务处理,其中纤程本身放弃其运行时间,以便其他纤程运行。
以下是一些比我更好地解释它的有用链接:
线程最初被创建作为轻量级进程。类似地,纤程是一种轻量级线程,简单地依赖于纤程本身相互调度,通过让出控制权来实现。
我猜下一步将是使用线程,在每次您想要执行指令时必须向它们发送信号(与我的5岁儿子类似 :-)。在旧日子里(甚至现在的某些嵌入式平台上),所有线程都是纤程,没有抢占并且您必须编写您的线程以使其表现良好。
线程由操作系统进行调度(抢占式)。操作系统可以随时停止或恢复线程,但是纤程(Fiber)更多地是自我管理(协作式),并相互让出执行权。也就是说,程序员控制纤程何时进行处理以及何时将处理切换到另一个纤程。