Answers:
用最简单的术语来说,线程通常被认为是抢占式的(尽管根据操作系统的不同,可能并不总是如此),而光纤则被认为是轻量级的协作线程。两者都是您的应用程序的单独执行路径。
带有线程:当前执行路径可以随时被中断或抢占(注意:该语句是一种概括,根据操作系统/线程包/等等,可能并不总是成立)。这意味着对于线程而言,数据完整性是一个大问题,因为一个线程可能在更新数据块的过程中停止,从而使数据完整性处于不良或不完整状态。这也意味着操作系统可以通过同时运行多个线程并将其留给开发人员来保护数据访问,从而利用多个CPU和CPU内核。
对于光纤:仅当光纤产生执行权时,才会中断当前执行路径(与上述相同)。这意味着光纤始终在定义明确的位置启动和停止,因此数据完整性不再是问题。另外,由于通常在用户空间中管理光纤,因此无需进行昂贵的上下文切换和CPU状态更改,从而使从一根光纤到另一根光纤的转换极为有效。另一方面,由于没有两个光纤可以完全同时运行,因此仅使用光纤将不会利用多个CPU或多个CPU内核。
线程使用抢占式调度,而光纤使用协作式调度。
使用线程,控制流可以随时中断,而另一个线程可以接管。使用多个处理器,您可以使多个线程全部同时运行(同时多线程或SMT)。因此,您必须非常小心并发数据访问,并使用互斥量,信号量,条件变量等保护数据。正确通常很棘手。
对于光纤,只有在告诉您时,控制才会切换,通常是通过名为的函数调用yield()
。这使并发数据访问更加容易,因为您不必担心数据结构或互斥锁的原子性。只要您不屈服,就不会有被抢占和让另一根光纤尝试读取或修改正在使用的数据的危险。但是,结果是,如果您的光纤陷入无限循环,则其他光纤将无法运行,因为您没有屈服。
您还可以混合使用线和纤维,这会引起两者都面临的问题。不建议这样做,但是如果仔细完成,有时可能是正确的选择。
首先,我建议阅读有关进程和线程之间差异的解释作为背景材料。
阅读完后,这很简单。可以在内核,用户空间中实现线程,也可以将两者混合使用。光纤基本上是在用户空间中实现的线程。
Tanenbaum在现代操作系统的11.4节“ Windows Vista中的进程和线程”中评论:
尽管对光纤进行了协同调度,但是如果有多个线程对光纤进行调度,则需要进行许多仔细的同步以确保光纤不会相互干扰。为了简化线程和光纤之间的交互,通常仅创建与要运行它们的处理器数量一样多的线程,并将每个线程仅在一组不同的可用处理器上运行,甚至仅在一个处理器上运行,这通常是有用的。每个线程然后可以运行光纤的特定子集,从而在线程和光纤之间建立一对多的关系,从而简化了同步。即使这样,纤维仍然存在许多困难。大多数Win32库完全不了解光纤,而试图将光纤当作线程使用的应用程序会遇到各种故障。内核不了解光纤,并且当光纤进入内核时,正在执行的线程可能会阻塞,内核将在处理器上调度任意线程,从而使其无法运行其他光纤。由于这些原因,除非从明显需要光纤提供功能的其他系统移植代码,否则很少使用光纤。
请注意,除了线程和光纤,Windows 7还引入了用户模式调度:
用户模式调度(UMS)是一种轻量级机制,应用程序可以使用该机制来调度其自己的线程。如果UMS线程在内核中阻塞,则应用程序可以在用户模式下的UMS线程之间进行切换,而无需涉及系统调度程序,并且可以重新获得对处理器的控制。UMS线程与光纤的不同之处在于,每个UMS线程都有自己的线程上下文,而不是共享单个线程的线程上下文。在用户模式下在线程之间切换的能力使UMS比线程池更有效地管理大量需要很少系统调用的短期工作项目。
有关线程,光纤和UMS的更多信息,请观看Dave Probert:Windows 7-用户模式调度程序(UMS)内部。
线程是由操作系统安排的(抢先式)。操作系统可以随时停止或恢复线程,但是光纤或多或少地自我管理(合作)并相互屈服。也就是说,程序员控制何时进行光纤处理以及何时该处理切换到另一根光纤。
线程通常依靠内核来中断线程,以便它或另一个线程可以运行(这被称为抢先式多任务处理),而光纤使用协作式多任务处理,而正是光纤本身放弃了它的运行时间,因此其他纤维可以运行。
一些比我可能更好地解释它的有用链接是:
Win32光纤定义实际上是Sun Microsystems建立的“ Green Thread”定义。无需将术语“光纤”浪费在某种类型的线程上,即在用户代码/线程库控制下在用户空间中执行的线程。
为了弄清楚参数,请看以下注释:
我们应该假设进程是由线程组成的,线程应该由纤维组成。考虑到这种逻辑,将光纤用于其他种类的线程是错误的。