线和光纤有什么区别?

时间:2009-04-28 04:27:20

标签: multithreading coroutine fiber

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

9 个答案:

答案 0 :(得分:141)

用最简单的术语来说,线程通常被认为是先发制人的(虽然这可能并非总是如此,这取决于操作系统),而光纤被认为是轻量级的协作线程。两者都是应用程序的独立执行路径。

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

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

答案 1 :(得分:51)

主题使用先发制人计划,而光纤使用合作计划。

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

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

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

答案 2 :(得分:42)

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

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

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

答案 3 :(得分:35)

首先,我建议阅读the difference between processes and threads的这种解释作为背景材料。

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

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

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

  

虽然纤维是合作安排的,但如果有多个   调度光纤的线程,很多细心的同步   要求确保纤维不会相互干扰。至   通常是简化线程和光纤之间的交互   用于创建与要运行的处理器一样多的线程   它们,并将每个运行的线程关联在一组不同的   可用的处理器,甚至只有一个处理器。每个线程都可以   然后运行一个特定的光纤子集,建立一个   线程和光纤之间的多对多关系简化了   同步。即便如此,仍有许多困难   纤维。大多数Win32库完全没有意识到光纤,而且   尝试使用光纤的应用程序就好像它们是线程一样   遇到各种失败。内核不了解纤维,   当光纤进入内核时,它正在执行的线程可以   块和内核将调度一个任意线程   处理器,使其无法运行其他光纤。对于这些   原因很少使用光纤,除非从其他端口移植代码   显然需要光纤提供的功能的系统。

答案 4 :(得分:12)

请注意,除了线程和光纤之外,Windows 7还引入了User-Mode Scheduling

  

用户模式调度(UMS)是一个   轻量化的机制   应用程序可以用来安排他们的   自己的线程。应用程序可以切换   在用户模式下的UMS线程之间   不涉及系统调度程序   如果,重新获得对处理器的控制权   内核中的UMS线程阻塞。 UMS   螺纹与纤维不同   每个UMS线程都有自己的线程   上下文而不是共享线程   单个线程的上下文。该   能够在线程之间切换   用户模式使UMS更有效   比用于管理大型的线程池   短期工作项目的数量   这需要很少的系统调用。

有关线程,光纤和UMS的更多信息,请访问Dave Probert: Inside Windows 7 - User Mode Scheduler (UMS)

答案 5 :(得分:7)

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

答案 6 :(得分:7)

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

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

答案 7 :(得分:6)

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

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

答案 8 :(得分:3)

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

澄清论点,请看以下评论​​:

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

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