在linux内核中,信号量被用来为数据的关键部分提供互斥,并且使用完成variables来在等待事件的2个线程之间进行同步。 为什么不使用信号灯来进行这种同步? 在信号量上使用完成variables是否有优势?
有两个原因可能需要使用完成而不是信号量。 首先,多个线程可以等待完成,并且可以通过一次调用complete_all()
来释放它们。 有一个信号量唤醒未知数量的线程会更复杂。
其次,如果等待线程要释放同步对象,则使用信号量时会出现竞争状态。 也就是说,在唤醒线程完成up()
之前,服务员可能会被唤醒并释放对象。 完成时不存在此种族。 (见Lasse的帖子)
为什么最初实现完成的解释: http : //lkml.indiana.edu/hypermail/linux/kernel/0107.3/0674.html
基本的总结是,我们有这种(相当常见的)等待某些事件的方式,通过在服务员堆栈上锁定一个锁定的信号,然后让服务员做一个“down()”,导致它阻塞它正在等待做了一个“上()”。
这个方法运行得很好, 但是它在SMP上的竞争非常小(并且不太可能),而不是像这个信号量的实现那么多。 我们可以修复信号量,但有几个原因不能:
- 信号量在非争用情况下被优化(有意)。 “等待完成”的用法有相反的默认情况
- 信号很精确地涉及到架构
由于这个优化。 试图改变他们是痛苦的地狱。相反,我介绍了“等待完成”的概念:
更多最近关于完成与信号量的话题http://lkml.org/lkml/2008/4/11/323