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