线和光纤有什么区别?

tat*_*tou 167 multithreading coroutine fiber

线和光纤有什么区别?我听说过来自红宝石的纤维,我读过听过它们有其他语言版本,有人可以用简单的语言向我解释一下螺纹和纤维之间有什么区别.

Jas*_*oco 150

在最简单的术语中,线程通常被认为是抢先的(尽管这可能并非总是如此,取决于操作系统),而光纤被认为是轻量级的协作线程.两者都是应用程序的独立执行路径.

使用线程:当前执行路径可能随时被中断或抢占(注意:此语句是一般化,并且可能并不总是成立,具体取决于OS /线程包/等).这意味着对于线程,数据完整性是一个大问题,因为在更新数据块的过程中可能会停止一个线程,从而使数据的完整性处于错误或不完整状态.这也意味着操作系统可以通过同时运行多个线程并将其留给开发人员来保护数据访问,从而利用多个CPU和CPU核心.

对于光纤:当光纤执行时,当前执行路径仅被中断(与上面相同的注释).这意味着光纤总是在明确定义的位置启动和停止,因此数据完整性不是问题.此外,由于光纤通常在用户空间中进行管理,因此无需进行昂贵的上下文切换和CPU状态更改,从而使从一个光纤更改为下一个光纤非常高效.另一方面,由于没有两根光纤可以完全同时运行,仅使用光纤不会利用多个CPU或多个CPU内核.

  • 有没有办法使用多个线程并行执行光纤? (7认同)
  • @Jason,当您声明〜“使用光纤时,当前执行路径仅在光纤产生执行时才会中断”和“光纤始终在明确定义的位置启动和停止,因此数据完整性不是问题”,您的意思是共享变量时,我们不需要使用“锁定机制”和 volatile 变量?或者你的意思是我们还需要做那些事情? (2认同)

Ada*_*eld 55

线程使用抢先调度,而光纤使用协作调度.

使用线程,控制流可以随时中断,另一个线程可以接管.使用多个处理器,您可以同时运行多个线程(同时多线程或SMT).因此,您必须非常小心并发数据访问,并使用互斥锁,信号量,条件变量等保护您的数据.要想做对,通常都很棘手.

使用光纤时,控制只会在您告诉它时切换,通常使用名为类似的函数调用yield().这使得并发数据访问更容易,因为您不必担心数据结构或互斥锁的原子性.只要你不屈服,就没有被抢占的危险,并且有另一种纤维试图读取或修改你正在使用的数据.因此,如果你的光纤进入一个无限循环,没有其他光纤可以运行,因为你没有屈服.

您还可以混合线和纤维,这会产生两者所面临的问题.不推荐,但如果仔细完成,有时可能是正确的做法.

  • 我认为无限循环只是一个需要修复的错误,并且当存在无限循环时,线程只具有相当模糊的优势.相关的非错误概念是当用户可能希望取消的长时间运行的过程时.在这种情况下,无论你使用线程还是光纤,长时间运行的进程都需要合作 - 只是杀死它的线程可能会使你的一些数据结构搞砸,所以一种更好的方法是例如长时间运行的进程线程会定期检查如果它被打断了 这与周期性纤维产生的差别不大. (3认同)

ito*_*son 42

在Win32中,光纤是一种用户管理的线程.光纤有自己的堆栈和自己的指令指针等,但操作系统不会调度光纤:您必须显式调用SwitchToFiber.相反,线程由操作系统预先安排.粗略地说,光纤是一个在应用程序/运行时级别管理的线程,而不是真正的OS线程.

结果是光纤更便宜并且应用程序对调度具有更多控制.如果应用程序创建了大量并发任务,并且/或者希望在运行时进行密切优化,这一点非常重要.例如,数据库服务器可能选择使用光纤而不是线程.

(对于同一个术语,可能还有其他用法;如上所述,这是Win32定义.)


Rob*_*nes 36

首先,我建议阅读过程和线程之间差异的这种解释作为背景材料.

一旦你读完它就会很直接.线程可以在内核,用户空间中实现,也可以两者混合使用.光纤基本上是在用户空间中实现的线程.

  • 通常称为线程的是在内核中实现的执行线程:所谓的内核线程.内核线程的调度由内核专门处理,尽管内核线程可以根据需要通过休眠自愿释放CPU.内核线程的优点是它可以使用阻塞I/O并让内核担心调度.它的主要缺点是线程切换相对较慢,因为它需要捕获到内核中.
  • 光纤是用户空间线程,其调度在一个进程下由一个或多个内核线程在用户空间中处理.这使得光纤切换速度非常快.如果将所有光纤分组在单个内核线程的上下文中访问一组特定的共享数据并将其调度由单个内核线程处理,则可以消除同步问题,因为光纤将有效地串行运行并且您已完成控制他们的日程安排.在单个内核线程下对相关光纤进行分组很重要,因为它们运行的​​内核线程可以被内核抢占.在许多其他答案中,这一点并未明确.此外,如果在光纤中使用阻塞I/O,则整个内核线程它是块的一部分,包括作为该内核线程一部分的所有光纤.

在现代操作系统的第11.4节"Windows Vista中的进程和线程"中,Tanenbaum评论道:

尽管光纤是协同安排的,但如果有多个线程调度光纤,则需要进行大量的仔细同步以确保光纤不会相互干扰.为了简化线程和光纤之间的交互,通常只需创建与运行它们的处理器一样多的线程,并将线程关联到每个运行仅在一组不同的可用处理器上,或者甚至只是一个处理器上.然后,每个线程可以运行光纤的特定子集,在线程和光纤之间建立一对多关系,这简化了同步.即便如此,纤维仍存在许多困难.大多数Win32库完全不知道光纤,尝试使用光纤的应用程序就像它们是线程一样会遇到各种故障.内核不了解光纤,当光纤进入内核时,它正在执行的线程可能会阻塞,内核将在处理器上调度任意线程,使其无法运行其他光纤.由于这些原因,很少使用光纤,除非从明确需要光纤提供的功能的其他系统移植代码.

  • 这是最完整的答案. (4认同)

Gra*_*ner 12

请注意,除了线程和光纤之外,Windows 7还引入了用户模式调度:

用户模式调度(UMS)是一种轻量级机制,应用程序可以使用它来调度自己的线程.应用程序可以在用户模式下在UMS线程之间切换,而不涉及系统调度程序,并且如果UMS线程在内核中阻塞,则重新获得对处理器的控制.UMS线程与光纤的不同之处在于每个UMS线程都有自己的线程上下文,而不是共享单个线程的线程上下文.在用户模式下在线程之间切换的能力使得UMS比线程池更有效,用于管理需要很少系统调用的大量短期工作项.

有关线程,光纤和UMS的更多信息,请参阅Dave Probert:Inside Windows 7 - 用户模式调度程序(UMS).


Arn*_*nce 7

线程由OS调度(先发制人).OS可以随时停止或恢复线程,但是光纤或多或少地管理它们(合作)并相互屈服.也就是说,程序员控制光纤何时进行处理以及何时处理切换到另一根光纤.


Mik*_*wen 7

线程通常依赖于内核来中断线程,因此它或其他线程可以运行(这更好地称为抢占式多任务处理),而光纤使用协作式多任务处理,其中光纤本身放弃其运行时间,以便其他纤维可以运行.

一些有用的链接解释它比我可能做的更好:


pax*_*blo 7

线程最初是作为轻量级进程创建的.以类似的方式,纤维是轻质的线,依靠(简单地)依赖于纤维本身以通过控制来彼此安排.

我想下一步将是你必须在每次你希望他们执行指令时发送信号的链(不像我的5yo儿子:-).在过去(甚至现在在一些嵌入式平台上),所有线程都是光纤,没有先发制人,你必须编写你的线程以表现得很好.


小智 6

Win32 光纤定义实际上是 Sun Microsystems 建立的“Green Thread”定义。没有必要在某种线程上浪费术语“纤程”,即在用户代码/线程库控制下在用户空间中执行的线程。

为了澄清这个论点,请看以下评论​​:

  • 借助超线程,多核 CPU 可以接受多个线程并将它们分配到每个核心上。
  • 超标量流水线 CPU 接受一个线程执行,并使用指令级并行 (ILP) 来更快地运行线程。我们可以假设一个线程被分成在并行管道中运行的并行纤维。
  • SMT CPU 可以接受多个线程,并将它们分解为指令纤维,以便在多个管道上并行执行,从而更有效地使用管道。

我们应该假设进程是由线程组成的,而线程应该是由纤维组成的。考虑到这一逻辑,将纤维用于其他类型的线程是错误的。