Multithreading 为什么在内核空间中实现的线程很慢?

Multithreading 为什么在内核空间中实现的线程很慢?,multithreading,performance,operating-system,kernel,Multithreading,Performance,Operating System,Kernel,当一个线程做了一些可能导致它在本地阻塞的事情时,例如,等待其进程中的另一个线程完成某些工作,它将调用运行时系统过程。此过程检查线程是否必须处于阻塞状态。如果是这样,它将线程的寄存器存储在线程表中,在表中查找准备运行的线程,并使用新线程保存的值重新加载机器寄存器。一旦堆栈指针和程序计数器被切换,新线程就会自动重新启动。如果机器碰巧有一条指令存储所有寄存器,另一条指令加载所有寄存器,那么整个线程切换只需少量指令即可完成。像这样进行线程切换至少要比捕获到内核快一个数量级,这是支持用户级线程包的有力论据

当一个线程做了一些可能导致它在本地阻塞的事情时,例如,等待其进程中的另一个线程完成某些工作,它将调用运行时系统过程。此过程检查线程是否必须处于阻塞状态。如果是这样,它将线程的寄存器存储在线程表中,在表中查找准备运行的线程,并使用新线程保存的值重新加载机器寄存器。一旦堆栈指针和程序计数器被切换,新线程就会自动重新启动。如果机器碰巧有一条指令存储所有寄存器,另一条指令加载所有寄存器,那么整个线程切换只需少量指令即可完成。像这样进行线程切换至少要比捕获到内核快一个数量级,这是支持用户级线程包的有力论据

资料来源:现代操作系统(Andrew S.Tanenbaum | Herbert Bos)

上面的论点有利于用户级线程。用户级线程实现被描述为管理所有进程的内核,其中各个进程可以有自己的运行时(由库包提供),用于管理该进程中的所有线程

当然,仅仅在运行时调用一个函数而不是捕获内核可能会少执行一些指令,但为什么差别如此巨大呢


例如,如果线程是在内核空间中实现的,那么每次必须创建线程时,程序都需要进行系统调用。对但是调用只涉及使用某些属性向线程表中添加一个条目(在用户空间线程中也是如此)。当必须进行线程切换时,内核可以简单地执行运行时(在用户空间)的操作。我在这里看到的唯一真正的区别是,内核参与了所有这一切。性能差异怎么会如此显著?

我认为解决这个问题的答案需要大量的操作系统和并行分布式计算知识(我不确定答案,但我会尽全力)


所以如果你仔细想想。库包的性能将比您在内核中编写的性能更高。在包中,这个代码给出的中断将立即被保持,所有的执行都将完成。当您在内核中写入时,其他中断可能会出现。再加上一次又一次地访问线程对内核来说是苛刻的,因为每次都会有中断。我希望这将是一个更好的看法

我认为这个问题的答案需要大量的操作系统和并行分布式计算知识(我不确定答案,但我会尽力)


所以如果你仔细想想。库包的性能将比您在内核中编写的性能更高。在包中,这个代码给出的中断将立即被保持,所有的执行都将完成。当您在内核中写入时,其他中断可能会出现。再加上一次又一次地访问线程对内核来说是苛刻的,因为每次都会有中断。我希望这将是一个更好的看法

说用户空间线程比内核空间线程更好是不正确的,因为每个线程都有自己的优缺点。 就用户空间线程而言,由于应用程序负责管理线程,因此更容易实现此类线程,并且此类线程不太依赖操作系统。但是,您无法利用多重处理的优势。 相反,内核空间模块是由操作系统处理的,因此您需要根据您使用的操作系统来实现它们,这将是一项更复杂的任务。但是,您可以更好地控制线程。
有关更全面的教程,请看一看。

说用户空间线程比内核空间线程更好是不正确的,因为每个线程都有自己的优缺点。 就用户空间线程而言,由于应用程序负责管理线程,因此更容易实现此类线程,并且此类线程不太依赖操作系统。但是,您无法利用多重处理的优势。 相反,内核空间模块是由操作系统处理的,因此您需要根据您使用的操作系统来实现它们,这将是一项更复杂的任务。但是,您可以更好地控制线程。 有关更全面的教程,请查看


在用户空间中实现为库包的线程的性能显著提高。为什么?

他们不是

事实上,大多数任务切换都是由线程阻塞(必须等待来自磁盘或网络的IO,或来自用户的IO,或等待时间的流逝,或等待与不同进程共享的某种信号量/互斥量,或来自不同进程的某种管道/消息/数据包)或线程解锁引起的(因为他们在等待发生的事情);大多数阻塞和取消阻塞的原因在某种程度上涉及内核(例如设备驱动程序、网络堆栈等);因此,当您已经在内核中时,在内核中执行任务切换会更快(因为它避免了切换到用户空间并在没有合理原因的情况下返回的开销)

用户空间任务切换“起作用”的地方是根本不涉及内核。这通常只发生在有人未能正确执行线程时(例如,他们有数千个线程和粗粒度锁定,并且由于锁争用而不断在线程之间切换,而不是像“工作线程池”这样合理的事情)。它仅在所有线程具有相同优先级时才起作用-您不希望出现属于一个进程的非常重要的线程没有CPU时间的情况,因为属于另一个进程的非常不重要的线程占用CPU(但这正是用户空间线程的情况,因为一个进程有