一、互斥量属性结构体(pthread_mutexattr_t)
二、互斥量属性
- 互斥量有3个属性:
- 进程共享属性(pshared)
- 健壮属性(robust)
- 类型属性(type)
三、互斥量属性的创建、销毁
pthread_mutexattr_init
#include <pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
// 返回值: 成功返回0; 失败返回错误编码
- 功能:对互斥量属性结构体进行初始化
- 调用此函数之后互斥量属性结构体的属性都是系统默认值,如果想要设置其他属性,还需要调用不同的函数进行设置
pthread_mutexattr_destroy
#include <pthread.h>
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
// 返回值: 成功返回0; 失败返回错误编码
四、进程共享属性(pshared)
备注
- POSIX.1中,进程共享属性是可选的
- 可以通过检测系统是否定义了_POSIX_THREAD_PROCESS_SHARED符号来判断平台是否支持进程共享属性。也可以把_SC_THREAD_PORCESS_SHARED参数传给sysconf函数进行检查。例如下面是在Ubuntu下进行的测试,支持线程共享属性:
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("_POSIX_THREAD_PROCESS_SHARED: %ld\n",sysconf(_SC_THREAD_PROCESS_SHARED));
return 0;
}
- 虽然这个选项并不是遵循POSIX标准的操作系统必须提供的,但是Single UNIX Specification要求遵循XSI标准的操作系统支持这个选项
进程共享属性的介绍
- 进程共享属性是指:允许相互独立的多个进程把同一个内存数据块映射到它们各自独立的地址空间中。就像多个线程访问共享数据一样,多个线程访问共享数据也需要同步(互斥)
进程共享属性取值
- pthread_mutexattr_setpshared函数的参数2可取的值如下:
- PTHREAD_PORCESS_PRIVATE(默认的):在进程中,多个线程可以访问同一个同步对象,这是默认的行为,在这种情况下,进程的互斥量属性为PTHREAD_PORCESS_PRIVATE,因此这是默认的情况。进程共享属性设置为PTHREAD_PORCESS_PRIVATE时,允许pthread线程库提供更有效的互斥量实现,这在多线程应用中是默认的情况。在多个进程共享多个互斥量的情况下,pthread线程库可以限制开销较大的互斥量实现(只有初始化屏障的那个进程内的多个线程可用)
- PTHREAD_PORCESS_SHARE:存在这样的机制,其允许相互独立的多个进程把同一个内存数据块映射到它们各自的独立的地址空间中。就像多个线程访问共享数据一样,多个进程访问共享数据也需要同步。如果进程共享属性设置为PTHREAD_PORCESS_SHARE时,从多个进程彼此之间共享的内存数据块中分配的互斥量就可以用于这些进程的同步(多进程中的多个线程可用)
相关函数
- pthread_mutexattr_setpshared:修改进程共享属性
- pthread_mutexattr_getpshared:得到进程共享属性
#include <pthread.h>
int pthread_barrierattr_setpshared(pthread_mutexattr_t* attr, int pshared);
int pthread_barrierattr_getpshared(const pthread_mutexattr_t* restrict attr, int* restrict pshared);
//返回值:成功返回0; 失败返回错误编码
五、健壮属性(robust)
健壮属性的介绍
- 健壮属性与多个进程间共享的互斥量有关
- 这意味着,当持有互斥量的进程终止时,需要解决互斥量状态恢复的问题。在这种情况发生时,互斥量处于锁定状态,恢复起来很苦难。其他阻塞在这个锁的进程将会一直阻塞下去
健壮属性取值
- pthread_mutexattr_setrobust函数的参数2可取的值如下:
- PTHREAD_MUTEX_STALLED(默认的):这意味着持有互斥量的进程终止时不需要采取特别的动作。在这种情况下,使用互斥量后的行为是未定义的,等待该互斥量解锁的应用程序会被有效地"拖住"
- PTHREAD_PORCESS_SHARE:这个值将导致线程调用pthread_mutex_lock获取锁,而该锁被另一个进程持有,但它终止时并没有对该锁进行结果,此时线程会阻塞,从pthread_mutex_lock返回的值为EOWNERDEAD而不是0。应用程序可以通过这个特殊的返回值获知,若有可能(要保护状态的细节以及如何进行恢复会因不同的应用程序而异),不管它们保护的互斥量状态如何,都需要进行恢复
- 使用健壮性的互斥量改变了我们使用pthread_mutex_lock的方式,因为现在必须检查3个返回值而不是之前的两个:不需要恢复的成功、需要恢复的成功、失败。但是,即使不用健壮的互斥量,也可以只检查成功或者失败
相关函数
- pthread_mutexattr_setrobust:修改进程健壮属性
- pthread_mutexattr_getrobust:得到进程健壮属性
#include <pthread.h>
int pthread_mutexattr_setrobust(pthread_mutexattr_t* attr,int robust);
int pthread_mutexattr_getrobust(const pthread_mutexattr_t* restrict attr,int* restrict robust);
//返回值:成功返回0;失败返回错误编码
pthread_mutex_consistent函数
- 如果应用状态无法恢复,在线程对互斥量解锁以后,该互斥量将处于永久不可用状态。为了避免这样的问题,线程可以调用pthread_mutex_consistent函数,指明与该互斥量相关的状态在互斥量解锁之前是一致的
#include <pthread.h>
int pthread_mutex_consistent(pthread_mutex_t *mutex);
//返回值:成功返回0;失败返回错误编码
- 如果线程没有先调用pthread_mutex_consitent就对互斥量进行了解锁,那么其他试图获取该互斥量的阻塞线程就会得到ENOTRECOVERABLE。如果发生这种情况,互斥量将不再使用。线程通过提前调用pthread_mutex_consistent,能让互斥量正常工作,这样它就可以持续被使用
六、类型属性(type)
类型属性
- 类型互斥量属性控制着互斥量的锁定特性
- POSIX.1定义了4种类型,如下:
- PTHREAD_MUTEX_NORMAL:一种标准互斥量类型,不做任何特殊的错误检查或死锁检测
- PTHREAD_MUTEX_ERRORCHECK:此互斥量类型提供错误检查
- PTHREAD_MUTEX_RECURSIVE:此互斥量类型允许同一线程在互斥量解锁之前对该互斥量进行多次加锁。递归互斥量维护锁的计数,在解锁次数和加锁次数不相同的情况下,不会释放锁。所以,如果对一个递归互斥量加锁两次,然后解锁一次,那么这个互斥量将依然处于加锁状态,对它再次解锁以前不能释放该锁
- PTHREAD_MUTEX_DEFAULT:此互斥量类型可以提供默认特性和行为。操作系统在实现它的时候可以把这种类型自由地映射到其他互斥量类型中的一种。例如,Linux 3.2.0把这种类型映射为普通的互斥量类型,而FreeBSD 8.0则把它映射为错误检查互斥量类型