可重入锁(递归锁) 互斥锁属性设置
前言:
上一次刷博客的時候,看到了自旋鎖,通過學習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_SHARED或PTHREAD_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指定的值不受支持。
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
總結
以上是生活随笔為你收集整理的可重入锁(递归锁) 互斥锁属性设置的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 自旋锁、互斥锁和信号量
 - 下一篇: 看图学习区块链概念