代码之家  ›  专栏  ›  技术社区  ›  tatsuhirosatou

线和纤维有什么区别?

  •  156
  • tatsuhirosatou  · 技术社区  · 16 年前

    线和纤维有什么区别?我听说过Ruby的纤维,我也读过,听说有其他语言的纤维,有人能简单地给我解释一下线和纤维之间的区别吗?

    9 回复  |  直到 7 年前
        1
  •  133
  •   Jason Coco superfell    16 年前

    在最简单的术语中,线程通常被认为是抢先的(尽管这可能并不总是正确的,取决于操作系统),而光纤则被认为是轻量、合作的线程。这两者都是应用程序的单独执行路径。

    with threads:当前执行路径可能随时被中断或抢占(注意:此语句是一种泛化语句,根据OS/threading package/etc的不同,可能并不总是保持为true)。这意味着对于线程来说,数据完整性是一个大问题,因为一个线程可能会在更新数据块的过程中停止,从而使数据的完整性处于坏的或不完整的状态。这也意味着操作系统可以利用多个CPU和CPU核心,同时运行多个线程,让开发人员负责保护数据访问。

    使用光纤:仅当光纤产生执行时,当前执行路径才会中断(如上所述)。这意味着光纤总是在定义良好的位置启动和停止,因此数据完整性就不再是一个问题。此外,由于光纤通常在用户空间中进行管理,因此不需要进行昂贵的上下文切换和CPU状态更改,从而使从一根光纤到下一根光纤的更改非常有效。另一方面,由于没有两条光纤可以同时运行,因此仅使用光纤不会利用多个CPU或多个CPU核心。

        2
  •  50
  •   Adam Rosenfield    16 年前

    线程使用 先发制人的 调度,而光纤使用 合作的 行程安排。

    有了线程,控制流随时可能被中断,另一个线程可以接管。使用多个处理器,可以同时运行多个线程( 同时 多线程,或smt)。因此,你必须 非常 小心并发数据访问,并使用互斥锁、信号量、条件变量等保护数据。通常很难纠正。

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

    你也可以把线和纤维混在一起,这会导致两者都面临的问题。不建议这样做,但如果小心做,有时是正确的。

        3
  •  42
  •   itowlson    16 年前

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

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

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

        4
  •  35
  •   Community CDub    8 年前

    首先,我建议你读一下 the difference between processes and threads 作为背景材料。

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

    • 通常称为线程的是在内核中实现的执行线程:即所谓的内核线程。内核线程的调度是由内核专门处理的,尽管内核线程可以根据需要通过休眠自动释放CPU。内核线程的优点是它可以使用阻塞I/O并让内核担心调度。它的主要缺点是线程切换相对较慢,因为它需要捕获到内核中。
    • 光纤是用户空间线程,其调度由单个进程下的一个或多个内核线程在用户空间中处理。这使得光纤交换非常快。如果您将访问特定共享数据集的所有光纤分组在单个内核线程的上下文中,并由单个内核线程处理它们的调度,那么您可以消除同步问题,因为光纤将有效地串行运行,并且您可以完全控制它们的调度。将相关的光纤分组在单个内核线程下是很重要的,因为内核可以预先清空正在运行的内核线程。这一点在许多其他答案中都不清楚。另外,如果在一个纤程中使用阻塞I/O,那么整个内核线程就是块的一部分,包括作为内核线程一部分的所有纤程。

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

    尽管纤维是协同调度的,如果有多个 线程调度光纤时,很多小心的同步是 要求确保光纤不相互干扰。到 简化线和纤维之间的相互作用,通常 只创建与要运行的处理器数量相同的线程很有用 它们,并且只在一组不同的 可用处理器,甚至一个处理器。每个线程都可以 然后运行光纤的特定子集,建立一个“1”… 线与纤维之间的许多关系,简化了 同步。尽管如此,在 纤维。大多数win32库完全不知道光纤,以及 尝试将光纤当作线程使用的应用程序将 遇到各种故障。内核不了解fi-bers, 当一根光纤进入内核时,它正在执行的线程 块和内核将在 处理器,使其无法运行其他光纤。为了这些 原因光纤很少使用,除非从其他端口移植代码 明确需要光纤提供功能的系统。

        5
  •  12
  •   Grant Wagner    16 年前

    注意,除了线程和光纤之外,Windows7还引入了 User-Mode Scheduling :

    用户模式调度(UMS)是 重量轻的机构 应用程序可以用于计划 自己的线程。应用程序可以切换 用户模式下的UMS线程之间 不涉及系统调度程序 如果 一个ums线程在内核中阻塞。UMS 线与纤维的区别在于 每个UMS线程都有自己的线程 上下文而不是共享线程 单个线程的上下文。这个 能够在线程之间切换 用户模式使UMS更高效 用于管理大型 短期工作项目的数量 这需要很少的系统调用。

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

        6
  •  7
  •   Arnold Spence    16 年前

    线程由操作系统调度(先发制人)。操作系统可以随时停止或恢复线程,但光纤或多或少会自我管理(合作)并相互让步。也就是说,程序员控制光纤何时进行处理,何时转换到另一根光纤。

        7
  •  7
  •   paxdiablo    16 年前

    线程最初是作为轻量级进程创建的。以类似的方式,纤维是一种轻量级的线,通过产生控制(简单地)依赖于纤维本身来调度彼此。

    我想下一步将是在你每次想要它们执行一条指令时都必须向它们发送一个信号的线(这和我的5yo儿子没有什么不同:—)。在过去(甚至现在在一些嵌入式平台上),所有线程都是光纤,没有先发制人的情况,您必须编写线程才能正常运行。

        8
  •  5
  •   Mike Lowen    16 年前

    线程通常依赖于内核来中断线程,这样它或另一个线程就可以运行(这通常被称为先发制人的多任务处理),而光纤使用合作的多任务处理,因为光纤本身放弃了其运行时间,所以其他光纤可以运行。

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

        9
  •  3
  •   billmic    10 年前

    Win32光纤定义实际上是在Sun Microsystems上建立的“绿线”定义。不需要在某类线程上浪费术语fiber,即在用户代码/线程库控制下在用户空间中执行的线程。

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

    • 使用超线程,多核CPU可以接受多个线程,并将它们分布在每个核心上。
    • 超标量流水线CPU接受一个线程来执行,并使用指令级并行(ILP)来更快地运行该线程。我们可以假设一根线被打断成平行的纤维,在平行的管道中运行。
    • SMT CPU可以接受多个线程,并将它们制动到指令光纤中 在多个管道上并行执行,更高效地使用管道。

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