抢先线程与非抢占线程

Alo*_*ave 51 unix linux multithreading pthreads

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

据我了解:

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

有人可以请:

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

Jer*_*fin 40

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

  • 关于yield()的一个注释:不要在Linux上使用它,因为它会导致可怕的性能.一个屈服的线程被推到线程调度的最后面,所以线程将不会被调度,直到*整个系统*中的其他所有东西都有机会. (3认同)

der*_*ert 23

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

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

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

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

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

  • @johnc我已经回滚了你的编辑."存在"是指那里 - 并发(一次运行多个线程)仅在您通过让步显式允许另一个线程运行时才存在."退出"没有意义.我也不确定你为什么改变*不是*到*不是*... (2认同)
  • @derobet那很好.这是一个似乎有意义的建议编辑,虽然由于建议中的拼写错误,我重新编辑了它.当时我将'yield'这个词与'exit'这个词联系起来而不是'exists'.说实话,这是错字; '不是 - >是'不'(或类似)导致我接受并编辑建议.我很抱歉,我对正确拼写的痴迷让我搞砸了你的答案 (2认同)

poo*_*ria 8

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

非抢占:

1.无上下文切换= 在非抢先模型中可以理解的头顶较少

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

先发制人:

优点:

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

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

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

坏处:

1.我们需要复杂的锁定算法,我们有应该处理的临界区问题

我们应该付出很大的开销