完成变量和信号量之间的差异

时间:2021-05-14 23:10:19

In the linux kernel, semaphores are used to provide mutual exclusion for critical sections of data and Completion variables are used to synchronize between 2 threads waiting on an event. Why not use semaphores for such a synchronization ? Is there any advantage of using a completion variable over a semaphore ?

在linux内核中,信号量用于为关键的数据部分提供互斥,而完成变量用于在等待事件的2个线程之间进行同步。为什么不使用信号量进行这种同步?在信号量上使用完成变量有什么好处吗?

2 个解决方案

#1


9  

There are two reasons you might want to use a completion instead of a semaphore. First, multiple threads can wait for a completion, and they can all be released with one call to complete_all(). It's more complex to have a semaphore wake up an unknown number of threads.

您可能希望使用完成而不是信号量有两个原因。首先,多个线程可以等待完成,并且可以通过一次调用complete_all()来释放它们。让信号量唤醒未知数量的线程会更复杂。

Second, if the waiting thread is going to deallocate the synchronization object, there is a race condition if you're using semaphores. That is, the waiter might get woken up and deallocate the object before the waking thread is done with up(). This race doesn't exist for completions. (See Lasse's post.)

其次,如果等待线程要释放同步对象,则在使用信号量时存在竞争条件。也就是说,在使用up()完成唤醒线程之前,服务员可能会被唤醒并释放对象。完成时不存在此种族。 (见Lasse的帖子。)

#2


12  

Explanation of why completions were originally implemented: http://lkml.indiana.edu/hypermail/linux/kernel/0107.3/0674.html

解释为什么最初实现完成:http://lkml.indiana.edu/hypermail/linux/kernel/0107.3/0674.html

The basic summary is that we had this (fairly common) way of waiting for certain events by having a locked semaphore on the stack of the waiter, and then having the waiter do a "down()" which caused it to block until the thing it was waiting for did an "up()".

基本的总结是我们有这种(相当常见的)等待某些事件的方式,通过在服务员的堆栈上有一个锁定的信号量,然后让服务员做一个“down()”导致它阻塞直到事物它正在等待“up()”。

This works fairly well, but it has a really small (and quite unlikely) race on SMP, that is not so much a race of the idea itself, as of the implementation of the semaphores. We could have fixed the semaphores, but there were a few reasons not to:

这种方法运行得相当不错,但它在SMP上的竞争非常小(而且非常不可能),与信号量的实现不同,这不是一个想法本身的竞赛。我们可以修复信号量,但有几个原因不能:

  • the semaphores are optimized (on purpose) for the non-contention case. The "wait for completion" usage has the opposite default case
  • 信号量针对非争用情况进行了优化(故意)。 “等待完成”用法具有相反的默认情况
  • the semaphores are quite involved and architecture-specific, exactly
    due to this optimization. Trying to change them is painful as hell.
  • 信号量非常复杂,特定于体系结构,正是由于这种优化。试图改变它们是痛苦的。

So instead, I introduced the notion of "wait for completion":

所以相反,我引入了“等待完成”的概念:

More recent thread about completions vs semaphores http://lkml.org/lkml/2008/4/11/323

关于完成与信号量的最新主题http://lkml.org/lkml/2008/4/11/323

#1


9  

There are two reasons you might want to use a completion instead of a semaphore. First, multiple threads can wait for a completion, and they can all be released with one call to complete_all(). It's more complex to have a semaphore wake up an unknown number of threads.

您可能希望使用完成而不是信号量有两个原因。首先,多个线程可以等待完成,并且可以通过一次调用complete_all()来释放它们。让信号量唤醒未知数量的线程会更复杂。

Second, if the waiting thread is going to deallocate the synchronization object, there is a race condition if you're using semaphores. That is, the waiter might get woken up and deallocate the object before the waking thread is done with up(). This race doesn't exist for completions. (See Lasse's post.)

其次,如果等待线程要释放同步对象,则在使用信号量时存在竞争条件。也就是说,在使用up()完成唤醒线程之前,服务员可能会被唤醒并释放对象。完成时不存在此种族。 (见Lasse的帖子。)

#2


12  

Explanation of why completions were originally implemented: http://lkml.indiana.edu/hypermail/linux/kernel/0107.3/0674.html

解释为什么最初实现完成:http://lkml.indiana.edu/hypermail/linux/kernel/0107.3/0674.html

The basic summary is that we had this (fairly common) way of waiting for certain events by having a locked semaphore on the stack of the waiter, and then having the waiter do a "down()" which caused it to block until the thing it was waiting for did an "up()".

基本的总结是我们有这种(相当常见的)等待某些事件的方式,通过在服务员的堆栈上有一个锁定的信号量,然后让服务员做一个“down()”导致它阻塞直到事物它正在等待“up()”。

This works fairly well, but it has a really small (and quite unlikely) race on SMP, that is not so much a race of the idea itself, as of the implementation of the semaphores. We could have fixed the semaphores, but there were a few reasons not to:

这种方法运行得相当不错,但它在SMP上的竞争非常小(而且非常不可能),与信号量的实现不同,这不是一个想法本身的竞赛。我们可以修复信号量,但有几个原因不能:

  • the semaphores are optimized (on purpose) for the non-contention case. The "wait for completion" usage has the opposite default case
  • 信号量针对非争用情况进行了优化(故意)。 “等待完成”用法具有相反的默认情况
  • the semaphores are quite involved and architecture-specific, exactly
    due to this optimization. Trying to change them is painful as hell.
  • 信号量非常复杂,特定于体系结构,正是由于这种优化。试图改变它们是痛苦的。

So instead, I introduced the notion of "wait for completion":

所以相反,我引入了“等待完成”的概念:

More recent thread about completions vs semaphores http://lkml.org/lkml/2008/4/11/323

关于完成与信号量的最新主题http://lkml.org/lkml/2008/4/11/323