线程控制之同步属性


就像线程具有属性一样,线程的同步对象(如互斥量、读写锁、条件变量、自旋锁和屏障)也有属性。http://www.cnblogs.com/nufangrensheng/p/3521654.html中介绍了自旋锁的唯一的一个属性,本篇介绍互斥量、读写锁、条件变量及屏障的属性。

1、互斥量属性

用pthread_mutexattr_init初始化pthread_mutexattr_t结构,用pthread_mutexattr_destroy来对该结构进行回收。

#include <pthread.h>

 pthread_mutexattr_init( pthread_mutexattr_t * pthread_mutexattr_destroy( pthread_mutexattr_t *

pthread_mutexattr_init函数用默认的互斥量属性初始化pthread_mutexattr_t结构。值得注意的两个属性是进程共享属性和类型属性。POSIX.1中,进程共享属性是可选的,可以通过检查系统中是否定义了_POSIX_THREAD_PROCESS_SHARED符号来判断这个平台是否支持进程共享这个属性,也可以在运行时把_SC_THREAD_PROCESS_SHARED参数传给sysconf函数进行检查。虽然这个选项并不是遵循POSIX标准的操作系统必须提供的,但是Single UNIX Specification要求遵循XSI标准的操作系统支持这个选项。

在进程中,多个线程可以访问同一个同步对象,这是默认的行为。在这种情况下,进程共享互斥量属性需要设置为PTHREAD_PROCESS_PRIVATE

存在这样一种机制:允许相互独立的多个进程把同一个内存区域映射到它们各自独立的地址空间中。就像多个线程访问共享数据一样,多个进程访问共享数据通常也需要同步。如果进程共享互斥量属性设置为PTHREAD_PROCESS_SHARED,从多个进程共享的内存区域中分配的互斥量就可以用于这些进程的同步

可以使用pthread_mutexattr_getpshared函数查询pthread_mutexattr_t结构,得到它的进程共享属性;可以用pthread_mutexattr_setpshared函数修改进程共享属性。

#include <pthread.h>

 pthread_mutexattr_getpshared(  pthread_mutexattr_t *restrict attr,  * pthread_mutexattr_setpshared( pthread_mutexattr_t *attr, 

进程共享互斥量属性设为PTHREAD_PROCESS_PRIVATE时,允许pthread线程库提供更加有效的互斥量实现,这在多线程应用程序中是默认的情况。在多个进程共享多个互斥量的情况下,pthread线程库可以限制开销较大的互斥量实现。

类型互斥量属性控制着互斥量的特性。POSIX.1定义了四种类型。PTHREAD_MUTEX_NORMAL类型是标准的互斥量类型,并不做任何特殊的错误检查或死锁检测。PTHREAD_MUTEX_ERRORCHECK互斥量类型提供错误检查。

PTHREAD_MUTEX_RECURSIVE互斥量类型允许同一线程在互斥量解锁之前对该互斥量进行多次加锁。用一个递归互斥量维护锁的计数。在解锁的次数和加锁的次数不相同的情况下不会释放锁。所以如果对一个递归互斥量加锁两次,然后对它解锁一次,这个互斥量依然处于加锁状态,在对它再次解锁以前不能释放该锁。

最后,PTHREAD_MUTEX_DEFAULT类型可以用于请求默认语义。操作系统在实现它的时候可以把这种类型自由地映射到其他类型。例如,在Linux中,这种类型映射为普通的互斥量类型。

四种类型的行为如表12-4所示。“不占用时解锁”这一栏指的是一个线程对被另一个线程加锁的互斥量进行解锁的情况;“在已解锁时解锁”这一栏指的是当一个线程对已经解锁的互斥量进行解锁时将会发生的情况,这通常是编码错误所致。

                                                 表12-4 互斥量类型行为

pthread_mutexattr_gettype( pthread_mutexattr_t * restrict attr, * pthread_mutexattr_settype( pthread_mutexattr_t *attr,

http://www.cnblogs.com/nufangrensheng/p/3521654.html中曾介绍过,互斥量可用于保护与条件变量关联的条件。在阻塞线程之前,pthread_cond_wait和pthread_cond_timedwait函数释放与条件相关的互斥量,这就允许其他线程获取互斥量、改变条件、释放互斥量并向条件变量发送信号。既然改变条件时必须占有互斥量,所以使用递归互斥量并不是好的办法。如果递归互斥量被多次加锁,然后用在调用pthread_cond_wait函数中,那么条件永远都不会得到满足,因为pthread_cond_wait所作的解锁操作并不能释放互斥量。

如果需要把现有的单线程接口放到多线程环境中,递归互斥量是非常有用的,但由于程序兼容性的限制,不能对函数接口进行修改。然而由于递归锁的使用需要一定技巧,它只应在没有其他可行方案的情况下使用。

未完待续...

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

相关内容