锁与信号量

本文提到的是posix的互斥锁和信号量。

最近测试了pthread_mutex_t和sem_t的性能,发现这两个东西并不存在什么关联,深层次的差别非常明显,具体来说,有以下几个地方:

1.pthread_mutex_lock/unlock操作与sem_wait/post操作,在循环测试中,前者时间大约是后者的2倍,循环越大,差距越小,但总是存在的。

2.pthread_mutex_lock/unlock文档里边明确提到,它们的错误码不包括EINTR,也就是说不会被信号打断,内部要么重启了系统调用,要么根本没有调用系统调用,或者直接屏蔽了信号;sem_wait/post则可以返回EINTR,这起码说明它可以被信号打断。

3.pthread_mutex_t有众多属性,提供死锁检测,递归锁之类的额外特性,但在默认情况下,很多非法操作都是未定义的,特别是多次unlock时;sem_t则没有这样的属性,多次wait只会造成阻塞。

4.pthread_mutex_t看起来并不能在进程间共享,这佐证了一个观点:它内部没有使用系统调用,实际用strace测试也发现它确实是在没有使用系统调用的情况下实现加锁的;sem_t则可以在进程间共享,这也反映了一个概念上的问题,mutex应该保护数据,而semaphore负责同步。

5.pthread_mutex_t提供了一个优先级的概念,锁本身的优先级低于调用线程优先级的情况下,操作是非法的;sem_t则没有这样的优先级策略。

6.pthread_mutex_t看起来还提供了一个拥有者的概念,调用pthread_mutex_lock返回之后,调用线程将获得锁,成为锁的拥有者。这一点的意义在于,试想如果这个锁具备递归属性,也就是可以多次加锁时,如果没有拥有者,将造成几个线程同时拥有这把互斥锁的局面,互斥锁就没有意义了。同样,在网上还发现一个讨论,另外一个线程尝试对不属于自己的mutex解锁会发生什么?答案是:如果开启了错误检测,则尝试unlock一个未上锁的锁,或者一个别人的锁,会返回错误,否则都是未定义的行为。

7.一个最明显的差别,pthread_mutex_t可以与pthread_cond_t配合使用,以支持事件驱动代码前行;sem_t则只能以固定时间轮询。

你可能感兴趣的:(信号量)