线和纤维有什么区别?
线和纤维有什么区别? 我听说过ruby的纤维,我听说他们有其他语言可以使用,有人可以简单地向我解释线程和光纤之间的区别。
用最简单的术语来说,线程通常被认为是抢占式的(尽pipe这可能并非总是如此,这取决于操作系统),而纤维被认为是轻量级的合作线程。 两者都是您的应用程序的独立执行path。
使用线程:当前的执行path可能随时被中断或抢占(注意:这个语句是泛化的,根据OS /线程包等可能不总是成立)。 这意味着对于线程来说,数据完整性是一个大问题,因为在更新数据块的过程中可能会停止一个线程,导致数据的完整性处于不良或不完整的状态。 这也意味着操作系统可以通过同时运行多个线程来利用多个CPU和CPU核心,并将其留给开发人员来保护数据访问。
使用光纤时:当前的执行path只在光纤产生执行时才中断(与上面相同)。 这意味着光纤始终在明确的位置开始和停止,所以数据完整性就不是问题了。 而且,由于光纤通常在用户空间中进行pipe理,所以不需要进行昂贵的上下文切换和CPU状态改变,使得从一根光纤到另一根光纤的切换非常高效。 另一方面,由于没有两条光纤可以同时运行,仅使用光纤就不会利用多个CPU或多个CPU核心。
在Win32中,光纤是一种用户pipe理的线程。 光纤有自己的堆栈和自己的指令指针等,但是光纤不是由OS安排的:你必须明确地调用SwitchToFiber。 相反,线程是由操作系统预先安排的。 所以粗略地说,光纤是一个在应用程序/运行时级别pipe理的线程,而不是一个真正的操作系统线程。
结果是光纤更便宜,应用程序对调度有更多的控制权。 如果应用程序创build了大量的并发任务,并且/或者想在运行时进行紧密优化,这可能很重要。 例如,数据库服务器可能会select使用光纤而不是线程。
(可能还有其他的用法,如上所述,这是Win32的定义。)
线程使用先占调度,而光纤使用协作调度。
有了一个线程,控制stream可以随时中断,另一个线程可以接pipe。 使用多个处理器,您可以同时运行多个线程( 同时multithreading或SMT)。 因此,您必须非常小心并发数据访问,并使用互斥锁,信号量,条件variables等来保护您的数据。 正确的做法往往非常棘手。
使用光纤时,只有在告诉它时,才会切换控件,通常使用名为yield()
的函数调用。 这使得并发数据访问更容易,因为您不必担心数据结构或互斥体的primefaces性。 只要你不屈服,就没有被抢占的危险,并且有另一种光纤试图读取或修改你正在使用的数据。 因此,如果你的光纤进入一个无限循环,没有其他光纤可以运行,因为你不屈服。
你也可以混合线程和纤维,这就产生了两者所面临的问题。 不推荐,但如果仔细做,有时候是正确的。
首先,我会build议阅读这个解释进程和线程之间的区别作为背景材料。
一旦你读到这是非常简单的。 线程可以在内核或用户空间中实现,也可以混合使用。 纤维基本上是在用户空间中执行的线程。
- 通常称为线程的是内核中执行的线程:所谓的内核线程。 内核线程的调度是由内核独占处理的,尽pipe内核线程可以通过在需要的时候自动释放CPU。 内核线程的优点是可以使用阻塞I / O,让内核担心调度。 它的主要缺点是线程切换比较慢,因为它需要陷入内核。
- 光纤是用户空间线程,其调度在一个进程下由一个或多个内核线程在用户空间中处理。 这使得光纤切换非常快。 如果您将所有光纤在单个内核线程的上下文中访问特定的一组共享数据并将其调度由单个内核线程处理,那么您可以消除同步问题,因为光纤将有效地以串行方式运行,并且您已经完成控制他们的调度。 在单个内核线程下分组相关的光纤是非常重要的,因为它们运行的内核线程可以被内核预先占用。 其他许多答案中都没有说明这一点。 另外,如果在光纤中使用阻塞I / O,则整个内核线程将成为块的一部分,包括作为该内核线程一部分的所有光纤。
在现代操作系统中的第11.4节“Windows Vista中的进程和线程”中,Tanenbaum评论道:
尽pipe光纤是合作安排的,但如果有多个线程调度光纤,则需要进行很多细致的同步,以确保光纤不会相互干扰。 为了简化线程和光纤之间的交互,通常只需创build与处理器运行的线程数相同数量的线程,然后将线程关联到每个只能在一组不同的可用处理器或甚至一个处理器上运行的线程。 然后,每个线程可以运行光纤的特定子集,从而在线程和光纤之间build立一对多的关系,从而简化了同步。 即使如此,纤维仍然有许多困难。 大多数Win32库完全不了解光纤,尝试使用光纤的应用程序就好像它们是线程一样会遇到各种故障。 内核不了解光纤,当光纤进入内核时,执行的线程可能会被阻塞,内核会在处理器上安排一个任意线程,使其不能运行其他光纤。 由于这些原因,光纤很less使用,除非从其他系统移植明确需要光纤提供的function的代码。
请注意,除了线程和光纤之外,Windows 7还引入了用户模式计划 :
用户模式调度(UMS)是一个轻量级的机制,应用程序可以使用它来调度自己的线程。 应用程序可以在用户模式下在UMS线程之间切换,而不涉及系统调度程序,并且如果UMS线程在内核中阻塞,则重新获得对处理器的控制。 UMS线程不同于光纤,因为每个UMS线程都有自己的线程上下文,而不是共享单个线程的线程上下文。 在用户模式下切换线程的能力使UMS比线程池更有效率,以pipe理大量需要less量系统调用的短期工作项。
有关线程,光纤和UMS的更多信息可以通过观看Dave Probert:Windows 7 – 用户模式计划程序(UMS)获得 。
线程由OS预先安排(抢先)。 OS可以随时停止或恢复线程,但是纤维或多或less地自我pipe理(合作)并相互屈服。 也就是说,程序员控制光纤何时处理,何时处理切换到另一个光纤。
线程最初创build为轻量级进程。 以类似的方式,纤维是一种轻量级的线,依靠(简单地)依靠纤维本身来安排彼此,通过屈服控制。
我想下一步将是你必须发送一个信号,每当你想要他们执行一个指令(不同于我的5yo儿子:-))。 在过去的时代(甚至现在在一些embedded式平台上),所有的线程都是光纤,没有抢占,你必须编写你的线程来performance得很好。
线程通常依靠内核来中断线程,以便它或另一个线程可以运行(这被称为“抢先式多任务”),而光纤使用协同式多任务处理,在这种情况下,光纤本身会放弃其运行时间,所以其他纤维可以运行。
一些有用的链接解释它比我可能做得更好的是:
Win32光纤定义实际上是在Sun Microsystemsbuild立的“绿色线程”定义。 在用户代码/线程库控制下,在用户空间中执行的线程没有必要在某种线程上浪费光纤。
澄清论点看下面的评论:
- 使用超线程技术,多核CPU可以接受多个线程,并在每个内核上分配一个线程。
- 超标量stream水线CPU接受一个线程执行,并使用指令级并行(ILP)来更快地运行线程。 我们可以假设一条线被分解成并行的并行光纤,
- SMT CPU可以接受多个线程,并将其制动为指令光纤,以便在多个pipe道上并行执行,从而更高效地使用pipe道。
我们应该假设过程是由线程组成的,线程应该由纤维组成。 考虑到这一逻辑,将光纤用于其他types的线程是错误的。
光纤是一个轻量级的线程,它使用协作式多任务而不是抢先式多任务。 正在运行的光纤必须显式“屈服”,以允许另一个光纤运行,这使得它们的实现比内核或用户线程更容易。
协程是一个概括子程序的组件,允许多个入口点在特定位置暂停和恢复执行。 与子例程不同的是,协程可以通过调用其他协程来退出,协程之后可能会返回到它们在原协程中被调用的地方。