可重入锁(递归锁)&互斥锁属性设置

版权声明:转载标明出处 https://blog.csdn.net/qq_38289815/article/details/83002037

前言:

上一次刷博客的时候,看到了自旋锁,通过学习Linux内核,对自旋锁有了一定的了解。在学习的过程中看到这么一句话——自旋锁是不可递归的。自旋锁不可递归,难道有可以递归的锁?带着这个问题,我们来看看什么是可以递归的锁。

 

回顾进程/线程同步方法

最常见的进程/线程的同步方法有互斥锁(或称互斥量Mutex),读写锁(rdlock),条件变量(cond),信号量(Semophore)等。在Windows系统中,临界区(Critical Section)和事件对象(Event)也是常用的同步方法。简单的说,互斥锁保护了一个临界区,在这个临界区中,一次最多只能进入一个线程。如果有多个进程在同一个临界区内活动,就有可能产生竞态条件(race condition)导致错误。

读写锁从广义的逻辑上讲,也可以认为是一种共享版的互斥锁。如果对一个临界区大部分是读操作而只有少量的写操作,读写锁在一定程度上能够降低线程互斥产生的代价。

条件变量允许线程以一种无竞争的方式等待某个条件的发生。当该条件没有发生时,线程会一直处于休眠状态。当被其它线程通知条件已经发生时,线程才会被唤醒从而继续向下执行。条件变量是比较底层的同步原语,直接使用的情况不多,往往用于实现高层之间的线程同步。使用条件变量的一个经典的例子就是线程池(Thread Pool)了。

在学习操作系统的进程同步原理时,讲的最多的就是信号量。通过精心设计信号量的PV操作,可以实现很复杂的进程同步情况(例如经典的哲学家就餐问题和理发店问题)。而现实的程序设计中,却极少有人使用信号量。能用信号量解决的问题似乎总能用其它更清晰更简洁的设计手段去代替信号量。

 

可递归锁与非递归锁(recursive mutex和non-recursive mutex)

在所有的线程同步方法中,互斥锁(mutex)的出场率远远高于其它方法。互斥锁的理解和基本使用方法都很容易。Mutex可以分为递归锁(recursive mutex)和非递归锁(non-recursive mutex)。可递归锁也可称为可重入锁(reentrant mutex),非递归锁又叫不可重入锁(non-reentrant mutex)。二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁。Windows下的Mutex和Critical Section是可递归的。Linux下的pthread_mutex_t锁默认是非递归的。可以显示的设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t设为递归锁。

在系统不支持递归锁,而又必须要使用时,就需要自己构造一个递归锁。通常,递归锁是在非递归互斥锁加引用计数器来实现的。简单的说,在加锁前,先判断上一个加锁的线程和当前加锁的线程是否为同一个。如果是同一个线程,则仅仅引用计数器加1。如果不是的话,则引用计数器设为1,记录当前线程号,并加锁。

递归锁与条件变量在一起使用的时候要特别小心,若线程A加了递归锁没有完全释放就进入了条件变量,等待唤醒。则线程B试图唤醒A时,由于A的递归锁没有完全释放,所以会导致死锁。递归锁在JAVA中仅仅用一个关键字synchronized就能实现,而且该关键字可以选择锁的对象。在C/C++中(linux下)就需要使用pthread库中提供的互斥锁,并且设置锁的属性为递归锁:

pthread_mutex_t Mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex,&attr);

 

 

互斥锁属性设置的相关函数及其说明

互斥锁属性

使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。要更改缺省的互斥锁属性,可以对属性对象进行声明和初始化。通常,互斥锁属性会设置在应用程序开头的某个位置,以便可以快速查找和轻松修改。

头文件:#include<pthread.h>
函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_init()函数是以动态方式创建互斥锁的,参数attr指定了新建互斥锁的属性。如果参数attr为空,则使用默认的互斥锁属性,默认属性为快速互斥锁。互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。函数成功执行后,互斥锁被初始化为未锁住态。

 

初始化互斥锁属性对象

使用pthread_mutexattr_init()可以将与互斥锁对象相关联的属性初始化为其缺省值。在执行过程中,线程系统会为每个属性对象分配存储空间。

int pthread_mutexattr_init(pthread_mutexattr_t *mattr);
#include<pthread.h>
pthread_mutexattr_t mattr;
int ret;/*initialize an attribute to default value*/
ret=pthread_mutexattr_init(&mattr);

mattr的类型为opaque,其中包含一个由系统分配的属性对象。mattr范围可能的值为PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。PTHREAD_PROCESS_PRIVATE是缺省值。对于互斥锁属性对象,必须首先通过调用pthread_mutexattr_destroy()将其销毁,才能重新初始化该对象。pthread_mutexattr_init()调用会导致分配类型为opaque的对象。如果未销毁该对象,则会导致内存泄漏。

返回值:pthread_mutexattr_init()成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。ENOMEM描述:内存不足,无法初始化互斥锁属性对象。

 

销毁互斥锁属性对象

pthread_mutexattr_destroy()可用来取消分配用于维护pthread_mutexattr_init()所创建的属性对象的存储空间。

int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
#include<pthread.h>
pthread_mutexattr_t mattr;
int ret;/*destroy an attribute*/
ret=pthread_mutexattr_destroy(&mattr);

返回值:pthread_mutexattr_destroy()成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。EINVAL描述:由mattr指定的值无效。

 

设置互斥锁的范围

pthread_mutexattr_setpshared()可用来设置互斥锁变量的作用域。

int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr,int pshared);
#include<pthread.h>
pthread_mutexattr_t mattr;
int ret;
ret=pthread_mutexattr_init(&mattr);/**resetting to its default value:private*/
ret=pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_PRIVATE);

互斥锁变量可以是进程专用的(进程内)变量,也可以是系统范围内的(进程间)变量。要在多个进程中的线程之间共享互斥锁,可以在共享内存中创建互斥锁,并将pshared属性设置为PTHREAD_PROCESS_SHARED。如果互斥锁的pshared属性设置为PTHREAD_PROCESS_PRIVATE(缺省值),则仅有那些由同一个进程创建的线程才能够处理该互斥锁。

返回值:pthread_mutexattr_setpshared()成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。EINVAL描述:由mattr指定的值无效。

 

获取互斥锁的范围

pthread_mutexattr_getpshared()可用来返回由pthread_mutexattr_setpshared()定义的互斥锁变量的范围。

int pthread_mutexattr_getpshared(pthread_mutexattr_t *mattr,int *pshared);
#include<pthread.h>
pthread_mutexattr_t mattr;
int pshared,ret;/*get pshared of mutex*/
ret=pthread_mutexattr_getpshared(&mattr,&pshared);

pshared值为PTHREAD_PROCESS_SHAREDPTHREAD_PROCESS_PRIVATE

返回值:pthread_mutexattr_getpshared()成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。EINVAL描述:由mattr指定的值无效。

 

设置互斥锁类型的属性

pthread_mutexattr_settype()可用来设置互斥锁的type属性。

int pthread_mutexattr_settype(pthread_mutexattr_t *attr,int type);

类型属性的缺省值为PTHREAD_MUTEX_DEFAULT。type参数指定互斥锁的类型。以下列出了有效的互斥锁类型:

PTHREAD_MUTEX_NORMAL描述:此类型的互斥锁不会检测死锁。如果线程在不首先解除互斥锁的情况下尝试重新锁定该互斥锁,则会产生死锁。尝试解除由其他线程锁定的互斥锁会产生不确定的行为。如果尝试解除锁定的互斥锁未锁定,则会产生不确定的行为。

PTHREAD_MUTEX_ERRORCHECK描述:此类型的互斥锁可提供错误检查。如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则会返回错误。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。

PTHREAD_MUTEX_RECURSIVE描述:如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁定该互斥锁。与PTHREAD_MUTEX_NORMAL类型的互斥锁不同,对此类型互斥锁进行重新锁定时不会产生死锁情况。多次锁定互斥锁需要进行相同次数的解除锁定才可以释放该锁,然后其他线程才能获取该互斥锁。如果线程尝试解除锁定的互斥锁已经由其他线程锁定,则会返回错误。如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。

PTHREAD_MUTEX_DEFAULT描述:如果尝试以递归方式锁定此类型的互斥锁,则会产生不确定的行为。对于不是由调用线程锁定的此类型互斥锁,如果尝试对它解除锁定,则会产生不确定的行为。对于尚未锁定的此类型互斥锁,如果尝试对它解除锁定,也会产生不确定的行为。允许在实现中将该互斥锁映射到其他互斥锁类型之一。对于Solaris线程,PTHREAD_PROCESS_DEFAULT会映射到PTHREAD_PROCESS_NORMAL。

返回值:如果运行成功,pthread_mutexattr_settype函数会返回零。否则,将返回用于指明错误的错误号。EINVAL描述:值为type无效。EINVAL描述:attr指定的值无效。

 

获取互斥锁的类型属性

pthread_mutexattr_gettype()可用来获取由pthread_mutexattr_settype()设置的互斥锁的type属性。

int pthread_mutexattr_gettype(pthread_mutexattr_t *attr,int *type);

类型属性的缺省值为PTHREAD_MUTEX_DEFAULT。

type参数指定互斥锁的类型。互斥锁类型包括:PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE 和PTHREAD_MUTEX_DEFAULT有关每种类型的说明,请参考设置互斥锁类型的属性的函数。

返回值:如果成功完成,pthread_mutexattr_gettype()会返回0。其他任何返回值都表示出现了错误。

 

设置互斥锁属性的协议

pthread_mutexattr_setprotocol()可用来设置互斥锁属性对象的协议属性。

int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,int protocol);

attr指示以前调用pthread_mutexattr_init()时创建的互斥锁属性对象。protocol可定义应用于互斥锁属性对象的协议。protocol可以是以下值之一:PTHREAD_PRIO_NONE、PTHREAD_PRIO_INHERIT或PTHREAD_PRIO_PROTECT。

PTHREAD_PRIO_NONE:线程的优先级和调度不会受到互斥锁拥有权的影响。

PTHREAD_PRIO_INHERIT:此协议值(如thrd1)会影响线程的优先级和调度。如果更高优先级的线程因thrd1所拥有的一个或多个互斥锁而被阻塞,而这些互斥锁是用PTHREAD_PRIO_INHERIT初始化的,则thrd1将以高于它的优先级或者所有正在等待这些互斥锁(这些互斥锁是thrd1指所拥有的互斥锁)的线程的最高优先级运行。如果thrd1因另一个线程(thrd3)拥有的互斥锁而被阻塞,则相同的优先级继承效应会以递归方式传播给thrd3。PTHREAD_PRIO_INHERIT可以避免优先级倒置。低优先级的线程持有较高优先级线程所需的锁时,便会发生优先级倒置。只有在较低优先级的线程释放该锁之后,较高优先级的线程才能继续使用该锁。设置PTHREAD_PRIO_INHERIT,以便按与预期的优先级相反的优先级处理每个线程。如果为使用协议属性值PTHREAD_PRIO_INHERIT初始化的互斥锁定义了_POSIX_THREAD_PRIO_INHERIT,则互斥锁的属主失败时会执行以下操作。属主失败时的行为取决于pthread_mutexattr_setrobust_np()的robustness参数的值。解除锁定互斥锁。互斥锁的下一个属主将获取该互斥锁,并返回错误EOWNERDEAD。互斥锁的下一个属主会尝试使该互斥锁所保护的状态一致。如果上一个属主失败,则状态可能会不一致。如果属主成功使状态保持一致,则可针对该互斥锁调用pthread_mutex_init()并解除锁定该互斥锁。

注意:如果针对以前初始化的但尚未销毁的互斥锁调用pthread_mutex_init(),则该互斥锁不会重新初始化。如果属主无法使状态保持一致,请勿调用pthread_mutex_init(),而是解除锁定该互斥锁。在这种情况下,所有等待的线程都将被唤醒。以后对pthread_mutex_lock()的所有调用将无法获取互斥锁,并将返回错误代码ENOTRECOVERABLE。现在,通过调用pthread_mutex_destroy()来取消初始化该互斥锁,即可使其状态保持一致。调用pthread_mutex_init()可重新初始化互斥锁。如果已获取该锁的线程失败并返回EOWNERDEAD,则下一个属主将获取该锁及错误代码EOWNERDEAD。

PTHREAD_PRIO_PROTECT当线程拥有一个或多个使用PTHREAD_PRIO_PROTECT初始化的互斥锁时,此协议值会影响其他线程(如thrd2)的优先级和调度。thrd2以其较高的优先级或者以thrd2拥有的所有互斥锁的最高优先级上限运行。基于被thrd2拥有的任一互斥锁阻塞的较高优先级线程对于thrd2的调度没有任何影响。如果某个线程调用sched_setparam()来更改初始优先级,则调度程序不会采用新优先级将该线程移到调度队列末尾。线程使用PTHREAD_PRIO_INHERIT或PTHREAD_PRIO_PROTECT初始化互斥锁,线程解除锁定使用PTHREAD_PRIO_INHERIT或PTHREAD_PRIO_PROTECT来解除初始化的互斥锁。一个线程可以同时拥有多个混合使用PTHREAD_PRIO_INHERIT和PTHREAD_PRIO_PROTECT初始化的互斥锁。在这种情况下,该线程将以通过其中任一协议获取的最高优先级执行。

返回值:如果成功完成,pthread_mutexattr_setprotocol()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexattr_setprotocol()将失败并返回对应的值。

ENOSYS描述:选项_POSIX_THREAD_PRIO_INHERIT和_POSIX_THREAD_PRIO_PROTECT均未定义并且该实现不支持此函数。

ENOTSUP描述:protocol指定的值不受支持。如果出现以下任一情况,pthread_mutexattr_setprotocol()可能会失败并返回对应的值。

EINVAL描述:attr或protocol指定的值无效。EPERM描述:调用方无权执行该操作。

 

获取互斥锁属性的协议

pthread_mutexattr_getprotocol()可用来获取互斥锁属性对象的协议属性。

int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,int *protocol);

attr指示以前调用pthread_mutexattr_init()时创建的互斥锁属性对象。protocol包含以下协议属性之一:PTHREAD_PRIO_NONE、PTHREAD_PRIO_INHERIT或PTHREAD_PRIO_PROTECT。

返回值:如果成功完成,pthread_mutexattr_getprotocol()会返回0。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_mutexattr_getprotocol()将失败并返回对应的值。

ENOSYS描述:_POSIX_THREAD_PRIO_INHERIT选项和_POSIX_THREAD_PRIO_PROTECT选项均未定义并且该实现不支持此函数。如果出现以下任一情况,pthread_mutexattr_getprotocol()可能会失败并返回对应的值。

EINVAL描述:attr指定的值无效。EPERM描述:调用方无权执行该操作。

 

设置互斥锁属性的优先级上限

pthread_mutexattr_setprioceiling()可用来设置互斥锁属性对象的优先级上限属性。

int pthread_mutexattr_setprioceiling(pthread_mutexatt_t *attr,int prioceiling,int *oldceiling);

attr指示以前调用pthread_mutexattr_init()时创建的互斥锁属性对象。

prioceiling指定已初始化互斥锁的优先级上限。优先级上限定义执行互斥锁保护的临界段时的最低优先级。prioceiling位于SCHED_FIFO所定义的优先级的最大范围内。要避免优先级倒置,请将prioceiling设置为高于或等于可能会锁定特定互斥锁的所有线程的最高优先级。oldceiling包含以前的优先级上限值。

返回值:如果成功完成,pthread_mutexattr_setprioceiling()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexattr_setprioceiling()将失败并返回对应的值。

ENOSYS描述:选项_POSIX_THREAD_PRIO_PROTECT未定义并且该实现不支持此函数。如果出现以下任一情况,pthread_mutexattr_setprioceiling()可能会失败并返回对应的值。

EINVAL描述:attr或prioceiling指定的值无效。EPERM描述:调用方无权执行该操作。

 

获取互斥锁属性的优先级上限

pthread_mutexattr_getprioceiling()可用来获取互斥锁属性对象的优先级上限属性。

int pthread_mutexattr_getprioceiling(const pthread_mutexatt_t *attr,int *prioceiling);

attr指定以前调用pthread_mutexattr_init()时创建的属性对象。

注意:仅当定义了_POSIX_THREAD_PRIO_PROTECT符号时,attr互斥锁属性对象才会包括优先级上限属性。

pthread_mutexattr_getprioceiling()返回prioceiling中已初始化互斥锁的优先级上限。优先级上限定义执行互斥锁保护的临界段时的最低优先级。prioceiling位于SCHED_FIFO所定义的优先级的最大范围内。要避免优先级倒置,请将prioceiling设置为高于或等于可能会锁定特定互斥锁的所有线程的最高优先级。

返回值:如果成功完成,pthread_mutexattr_getprioceiling()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexattr_getprioceiling()将失败并返回对应的值。

ENOSYS描述:_POSIX_THREAD_PRIO_PROTECT选项未定义并且该实现不支持此函数。如果出现以下任一情况,pthread_mutexattr_getprioceiling()可能会失败并返回对应的值。

EINVAL描述:attr指定的值无效。EPERM描述:调用方无权执行该操作。

 

设置互斥锁的优先级上限

pthread_mutexattr_setprioceiling()可用来设置互斥锁的优先级上限。

int pthread_mutex_setprioceiling(pthread_mutex_t *mutex,int prioceiling,int *old_ceiling);

pthread_mutex_setprioceiling()可更改互斥锁mutex的优先级上限prioceiling。pthread_mutex_setprioceiling()可锁定互斥锁(如果未锁定的话),或者一直处于阻塞状态,直到pthread_mutex_setprioceiling()成功锁定该互斥锁,更改该互斥锁的优先级上限并将该互斥锁释放为止。锁定互斥锁的过程无需遵循优先级保护协议。

如果pthread_mutex_setprioceiling()成功,则将在old_ceiling中返回以前的优先级上限值。如果pthread_mutex_setprioceiling()失败,则互斥锁的优先级上限保持不变。返回值:如果成功完成,pthread_mutex_setprioceiling()会返回0。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_mutexatt_setprioceiling()将失败并返回对应的值。

ENOSYS描述:选项_POSIX_THREAD_PRIO_PROTECT未定义并且该实现不支持此函数。如果出现以下任一情况,pthread_mutex_setprioceiling()可能会失败并返回对应的值。

EINVAL描述:prioceiling所请求的优先级超出了范围。EINVAL描述:mutex指定的值不会引用当前存在的互斥锁。ENOSYS描述:该实现不支持互斥锁的优先级上限协议。EPERM描述:调用方无权执行该操作。

 

获取互斥锁的优先级上限

pthread_mutexattr_getprioceiling()可用来获取互斥锁的优先级上限。

int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,int *prioceiling);

返回值:如果成功完成,pthread_mutex_getprioceiling()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexatt_getprioceiling()将失败并返回对应的值。

ENOSYS描述:_POSIX_THREAD_PRIO_PROTECT选项未定义并且该实现不支持此函数。如果出现以下任一情况,pthread_mutex_getprioceiling()可能会失败并返回对应的值。

EINVAL描述:mutex指定的值不会引用当前存在的互斥锁。ENOSYS描述:该实现不支持互斥锁的优先级上限协议。EPERM描述:调用方无权执行该操作。

 

设置互斥锁的强健属性

pthread_mutexattr_setrobust_np()可用来设置互斥锁属性对象的强健属性。

int pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr,int *robustness);

注意:仅当定义了符号_POSIX_THREAD_PRIO_INHERIT时,pthread_mutexattr_setrobust_np()才适用。attr指示以前通过调用pthread_mutexattr_init()创建的互斥锁属性对象。robustness定义在互斥锁的属主失败时的行为。pthread.h中定义的robustness的值为PTHREAD_MUTEX_ROBUST_NP或PTHREAD_MUTEX_STALLED_NP(缺省值)。

PTHREAD_MUTEX_ROBUST_NP如果互斥锁的属主失败,则以后对pthread_mutex_lock()的所有调用将以不确定的方式被阻塞。PTHREAD_MUTEX_STALLED_NP互斥锁的属主失败时,将会解除锁定该互斥锁。互斥锁的下一个属主将获取该互斥锁,并返回错误EOWNWERDEAD。

注意:应用程序必须检查pthread_mutex_lock()的返回代码,查找返回错误EOWNWERDEAD的互斥锁。互斥锁的新属主应使该互斥锁所保护的状态保持一致。如果上一个属主失败,则互斥锁状态可能会不一致。如果新属主能够使状态保持一致,请针对该互斥锁调用pthread_mutex_consistent_np(),并解除锁定该互斥锁。如果新属主无法使状态保持一致,请勿针对该互斥锁调用pthread_mutex_consistent_np(),而是解除锁定该互斥锁。所有等待的线程都将被唤醒,以后对pthread_mutex_lock()的所有调用都将无法获取该互斥锁。返回代码为ENOTRECOVERABLE。通过调用pthread_mutex_destroy()取消对互斥锁的初始化,并调用pthread_mutex_int()重新初始化该互斥锁,可使该互斥锁保持一致。如果已获取该锁的线程失败并返回EOWNERDEAD,则下一个属主获取该锁时将返回代码EOWNERDEAD。

返回值:如果成功完成,pthread_mutexattr_setrobust_np()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexattr_setrobust_np()将失败并返回对应的值。

ENOSYS描述:选项_POSIX_THREAD_PRIO__INHERIT未定义,或者该实现不支持pthread_mutexattr_setrobust_np()。

ENOTSUP描述:robustness指定的值不受支持。pthread_mutexattr_setrobust_np()可能会在出现以下情况时失败:

EINVAL描述:attr或robustness指定的值无效。

 

获取互斥锁的强健属性

pthread_mutexattr_getrobust_np()可用来获取互斥锁属性对象的强健属性。

int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr,int *robustness);

注意:仅当定义了符号_POSIX_THREAD_PRIO_INHERIT时,pthread_mutexattr_getrobust_np()才适用。

attr指示以前通过调用pthread_mutexattr_init()创建的互斥锁属性对象。robustness是互斥锁属性对象的强健属性值。

返回值:如果成功完成,pthread_mutexattr_getrobust_np()会返回0。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_mutexattr_getrobust_np()将失败并返回对应的值。

ENOSYS描述:选项_POSIX_THREAD_PRIO__INHERIT未定义,或者该实现不支持pthread_mutexattr_getrobust_np()。pthread_mutexattr_getrobust_np()可能会在出现以下情况时失败:

EINVAL描述:attr或robustness指定的值无效。

 

应用互斥量需要注意

互斥量需要时间来加锁和解锁。锁住较少互斥量的程序通常运行得更快。所以,互斥量应该尽量少,够用即可,每个互斥量保护的区域应则尽量大。互斥量的本质是串行执行。如果很多线程需要领繁地加锁同一个互斥量,则线程的大部分时间就会在等待,这对性能是有害的。如果互斥量保护的数据(或代码)包含彼此无关的片段,则可以特大的互斥量分解为几个小的互斥量来提高性能。这样,任意时刻需要小互斥量的线程减少,线程等待时间就会减少。所以,互斥量应该足够多(到有意义的地步),每个互斥量保护的区域则应尽量的少。

参考:

https://blog.csdn.net/kingmax26/article/details/5338065

https://blog.csdn.net/jasmineal/article/details/8807744

https://blog.csdn.net/zouxinfox/article/details/5838861

 

猜你喜欢

转载自blog.csdn.net/qq_38289815/article/details/83002037
今日推荐