抢先线程与非抢占线程

时间:2010-11-10 17:30:11

标签: linux multithreading unix pthreads

有人可以解释先发制人线程模型和非先发制人线程模型之间的区别吗?

根据我的理解:

  • 非抢占式线程模型: 线程启动后,无法停止或在线程完成任务之前无法将控件传输到其他线程。
  • 抢先线程模型: 允许运行时随时介入并从一个线程手动控制到另一个线程。优先级较高的线程优先于优先级较低的线程。

有人可以:

  1. 解释理解是否正确。
  2. 解释两种模型的优点和缺点。
  3. 何时使用真正有用的内容的一个例子。
  4. 如果我在Linux(系统v或Pthread)中创建一个线程而没有提及任何选项(有没有?)默认情况下使用的线程模型是抢占式线程模型?

4 个答案:

答案 0 :(得分:35)

  1. 不,你的理解并不完全正确。非抢先(也称为协作)线程通常手动产生控制以让其他线程在完成之前运行(尽管由该线程调用yield()(或其他)来实现这一点。
  2. 抢占线程更简单。协作线程的开销较小。
  3. 通常使用抢占式。如果您发现您的设计有很多线程切换开销,那么协作线程将是一种可能的优化。在许多(大多数?)情况下,这将是一项相当大的投资,但收益最小。
  4. 是的,默认情况下你会获得抢占式线程,但是如果你四处寻找CThreads包,它会支持协作线程。很少有人(现在)想要合作线程,我不确定它在过去十年内是否已经更新......

答案 1 :(得分:20)

非抢先线程也称为协作线程。这些的一个例子是POE(Perl)。另一个例子是经典Mac OS(在OS X之前)。协作线程专用CPU,直到它们放弃。然后调度程序选择另一个要运行的线程。

抢先线程可以像协作线程一样自愿放弃CPU,但是当它们没有时,它将从它们中获取,并且调度程序将启动另一个线程。 POSIX& SysV线程属于这一类。

协作线程的巨大优势是效率更高(至少在单核机器上)和更容易处理并发:它只在你产生控制时才存在,因此不需要锁定。

抢占线程的巨大优势是更好的容错能力:单个线程无法产生不会阻止所有其他线程执行。由于多个线程同时执行,因此通常在多核机器上工作得更好。最后,你不必担心确保你不断屈服。这在内部可能非常烦人,例如,大量的运算循环。

当然,你可以混合使用它们。单个抢占线程可以在其中运行许多协作线程。

答案 2 :(得分:7)

如果您使用非抢占式,则并不意味着当进程等待I / O时,进程不会执行上下文切换。调度员将根据调度模型选择另一个进程。在这个模型中,我们必须相信这个过程。

<强>非抢占:

1.无上下文切换=少头顶,这在非抢先模型中是明智的

2.它更容易处理,因为它可以在单核处理器上处理

<强>抢占

<强>优势:

1.在这个模型中,我们优先考虑可以帮助我们更好地控制运行过程

2.我们可以看到更好的并发性

3.我们可以在不阻塞整个系统的情况下处理系统调用

<强>缺点:

1.我们需要复杂的锁定算法,我们有应该处理的关键部分问题

2.经常支付一大笔费用

答案 3 :(得分:0)

合作(非抢占式)模型中,一旦线程获得控制权,它将继续运行,直到明确产生控制权或阻塞为止。

抢占模式中,允许虚拟机随时介入并将控制权从一个线程转移到另一个线程。两种模型都有其优点和缺点。

通常,Java线程在优先级之间是抢占式的。较高优先级的线程优先于较低优先级的线程。如果较高优先级的线程进入睡眠或阻塞状态,则可以运行较低优先级的线程(假设有一个可用线程并准备运行)。

但是,一旦较高优先级的线程唤醒或解除阻塞,它将中断较低优先级的线程并运行,直到完成,再次阻塞或被更高优先级的线程抢占。

Java语言规范偶尔允许VM运行较低优先级的线程,而不是运行可运行的较高优先级的线程,但这在实践中是不寻常的。

但是,Java语言规范中没有任何内容指定优先级相等的线程应该发生的情况。在某些系统上,这些线程将被分时,运行时将为线程分配一定的时间。时间到时,运行时会抢占正在运行的线程并切换到具有相同优先级的下一个线程。

在其他系统上,运行中的线程不会被优先级相同的线程抢占。它会继续运行,直到阻塞,显式产生控制权或被更高优先级的线程抢占。

关于德罗伯特和穷人的优势,他们都非常清楚地强调了它们。