14-与其他同步技术比较
53.5 与其他同步技术比较
本节将比较POSIX信号量和其他两种同步技术:System V信号量和互斥体。
POSIX信号量与System V信号量比较
POSIX信号量和System V信号量都可以用来同步进程的动作。51.2节列出了POSIX IPC与System V IPC相比具备的几项优势:POSIX IPC接口更加简单并且与传统的UNIX文件模型更加一致,同时POSIX IPC对象是引用计数的,这样就简化了确定何时删除一个IPC对象的工作。这些常规优势同样也是POSIX(命名)信号量优于System V信号量的地方。
与System V信号量相比,POSIX信号量还具备下列优势。
- POSIX信号量接口与System V信号量接口相比要简单许多。这种简单性并没有以牺牲功能的强大性为代价。
- POSIX命名信号量消除了System V信号量存在的初始化问题(47.5节)。
- 将一个POSIX未命名信号量与动态分配的内存对象关联起来更加简单:只需要将信号量嵌入到对象中即可。
- 在高度频繁地争夺信号量的场景中(即信号量上的操作经常因另一个进程将信号量值设置成一个阻止操作立即往前执行的的值而阻塞),那么POSIX信号量的性能与System V信号量的性能是类似的。但在争夺信号量不那么频繁的场景中(即信号量的值能够让操作正常向前执行而不会阻塞操作),POSIX信号量的性能要比System V信号量好很多。(在笔者测试的系统上,两者在性能上的差异要超过一个数量级,参见练习53-4。)POSIX在这种场景中之所以能够做得更好是因为它们的实现方式只有在发生争夺的时候才需要执行系统调用,而System V信号量操作则不管是否发生争夺都需要执行系统调用。
然而POSIX信号量与System V信号量相比也存在下列劣势。
- POSIX信号量的可移植性稍差。(在Linux上,直到内核2.6才开始支持命名信号量。)
- POSIX信号量不支持System V信号量中的撤销特性。(然而在47.8节中指出过这个特性在一些场景中可能并没有太大的用处。)
POSIX信号量与Pthreads互斥体对比
POSIX信号量和Pthreads互斥体都可以用来同步同一个进程中的线程的动作,并且它们的性能也是相近的。然而互斥体通常是首选方法,因为互斥体的所有权属性能够确保代码具有良好的结构性(只有锁住互斥体的线程才能够对其进行解锁)。与之形成对比的是,一个线程能够递增一个被另一个线程递减的信号量。这种灵活性会导致产生结构糟糕的同步设计。(正是因为这个原因,信号量有时候会被称为并发式编程中的“goto”。)
互斥体在一种情况下是不能用在多线程应用程序中的,在这种情况下信号量可能就成了一种首选方法了。由于信号量是异步信号安全的(参见表21-1),因此在一个信号处理器中可以使用sem_post()函数来与另一个线程进行同步。而信号量就无法完成这项工作,因为操作互斥体的Pthreads函数不是异步信号安全的。然而通常处理异步信号的首选方法是使用sigwaitinfo()(或类似的函数)来接收这些信号,而不是使用信号处理器(33.2.4节),因此信号量比互斥体在这一点上的优势很少有机会发挥出来。