參考文件1
參考文件2
遞迴鎖值得注意的兩個屬性是程序共享屬性和型別屬性
#include
intpthread_mutexattr_init
( pthread_mutexattr_t *attr )
;int
pthread_mutexattr_destroy
( pthread_mutexattr_t *attr )
;int
pthread_mutexattr_getpshared
(pthread_mutexattr_t *attr,
int*pshared)
;int
pthread_mutexattr_setpshared
(pthread_mutexattr_t *attr,
int pshared)
;返回值:若成功則返回0,否則返回錯誤編號
pshared的取值
thread_process_shared:那麼由這個屬性物件建立的互斥鎖將被儲存在共享記憶體中,可以被多個程序中的執行緒共享。
pthread_process_private:那麼只有和建立這個互斥鎖的執行緒在同乙個程序中的執行緒才能訪問這個互斥鎖。
int
pthread_mutexattr_settype
(pthread_mutexattr_t *attr,
int kind)
;int
pthread_mutexattr_gettype
(pthread_mutexattr_t *attr,
int*kind)
;
pthread_mutex_normal,不進行deadlock detection(死鎖檢測)。企圖進行relock這個mutex會導致deadlock.如果乙個執行緒對未加鎖的或已經unlock的mutex物件進行unlock操作,結果是不未知的。
pthread_mutex_errorcheck,那麼將進行錯誤檢查。如果乙個執行緒企圖對乙個已經鎖住的mutex進行relock,將返回乙個錯誤。如果乙個執行緒對未加鎖的或已經unlock的mutex物件進行unlock操作,將返回乙個錯誤。
pthread_mutex_recursive,mutex會有乙個鎖住次數(lock count)的概念。當乙個執行緒成功地第一次鎖住乙個mutex的時候,鎖住次數(lock count)被設定為1,每一次乙個執行緒unlock這個mutex的時候,鎖住次數(lock count)就減1。當鎖住次數(lock count)減少為0的時候,其他執行緒就能獲得該mutex鎖了。如果乙個執行緒對未加鎖的或已經unlock的mutex物件進行unlock操作,將返回乙個錯誤,如果乙個執行緒對這種型別的互斥鎖重複上鎖,不會引起死鎖,乙個執行緒對這類互斥鎖的多次重複上鎖必須由這個執行緒來重複相同數量的解鎖,這樣才能解開這個互斥鎖,別的執行緒才能得到這個互斥鎖。如果試**鎖乙個由別的程序鎖定的互斥鎖將會返回乙個錯誤**。如果乙個執行緒試**鎖已經被解鎖的互斥鎖也將會返回乙個錯誤**。這種型別的互斥鎖只能是程序私有的(作用域屬性為pthread_process_private)。
pthread_mutex_default,企圖遞迴的獲取這個mutex的鎖的結果是不確定的。unlock乙個不是被呼叫執行緒鎖住的mutex的結果也是不確定的。企圖unlock乙個未被鎖住的mutex導致不確定的結果。
linux下的pthread_mutex_t鎖預設是非遞迴的
根據上文分析,在同乙個執行緒中,如果想要多次獲得乙個鎖,只能使用遞迴鎖pthread_mutex_recursive,不然會出現死鎖,其次,遞迴鎖是不被提倡的,用到遞迴鎖說明這個**設計是有問題的。更好的做法是,提取出乙個被兩個個公有函式呼叫的私有函式,這個私有函式無需鎖定mutex
main()
func1()
func2()
兩種辦法:
將原來的加鎖的函式分為不加鎖的部分
作為對外介面的public函式只能呼叫無鎖的私有變數函式,而不能互相呼叫
main()
func1()
func2()
//111111原來的版本
mutexlock mutex;
void
foo(
)void
bar(
)// 222222222不加鎖版本
void
foo_nolock()
// 加鎖版本
void
fun(
)// 33333333private版本
class t
作為對外介面的public函式只能呼叫無鎖的私有變數函式,而不能互相呼叫。在函式具體實現上,這兩種方法基本是一樣的。
先讀在寫,阻塞
先寫在讀,死鎖
先讀後讀,正常
先寫在寫,死鎖
在posix標準中,如果乙個執行緒先獲得寫鎖,又獲得讀鎖,則結果是無法**的。這就是為什麼程式1的執行出人所料。需要注意的是,讀鎖是遞迴鎖(即可重入),寫鎖是非遞迴鎖(即不可重入)。因此程式3不會死鎖,而程式4會一直阻塞。
#include
intmain()
/*程式2*/
#include
intmain()
/*程式3*/
#include
intmain()
/*程式4*/
#include
intmain()
讀寫鎖與互斥量類似,也具有屬性。用pthread_rwlockattr_init初始化pthread_rwlockattr_t結構,用pthread_rwlockattr_destroy**結構
#include
intpthread_rwlockattr_init
(pthread_rwlockattr_t *attr)
;int
pthread_rwlockattr_destroy
(pthread_rwlockattr_t *attr)
;兩者的返回值都是:若成功則返回0,否則返回錯誤編號
讀寫鎖支援的唯一屬性是程序共享屬性,該屬性與互斥量的程序共享屬性相同。就像互斥量的程序共享屬性一樣,用一對函式來讀取和設定讀寫鎖的程序共享屬性。
#include
#include
intpthread_rwlockattr_getpshared
(const pthread_rwlockattr_t * restrict attr,
int*restrict pshared)
;int
pthread_rwlockattr_setpshared
(pthread_rwlockattr_t *attr,
int pshared)
;兩者的返回值都是:若成功則返回0,否則返回錯誤編號
條件變數也有屬性。與互斥量和讀寫鎖類似,有一對函式用於初始化和**條件變數屬性。
#include
intpthread_condattr_init
(pthread_condattr_t *attr)
;int
pthread_condattr_destroy
(pthread_condattr_t *attr)
;兩者的返回值都是:若成功則返回0,否則返回錯誤編號
與其他的同步原語一樣,條件變數支援程序共享屬性。
#include
intpthread_condattr_getpshared
(const pthread_condattr_t *restrict attr,
int*restrict pshared)
;int
pthread_condattr_setpshared
(pthread_condattr_t *attr,
int pshared)
;兩者的返回值都是:若成功則返回0,否則返回錯誤編號
屏障也具有屬性。我們可以使用pthread_barrierattr_init函式初始化乙個屏障屬性,使用pthread_barrierattr_destroy函式**屏障屬性。
#include
intpthread_barrierattr_init
(pthread_barrierattr_t *attr)
;int
pthread_barrierattr_destroy
(pthread_barrierattr_t attr)
;兩個函式的返回值都是:若成功則返回0,否則返回錯誤編號
唯一的乙個屏障屬性是程序共享屬性。
#include
intpthread_barrierattr_getpshared
(const pthread_barrierattr_t *restrict attr,
int*restrict pshared)
;int
pthread_barrierattr_setpshared
(pthread_barrierattr_t *attr,
int*pshared)
;兩個函式的返回值都是:若成功則返回0,否則返回錯誤編號
執行緒同步與鎖
二元訊號量和多元訊號量,是乙個變數,獲取 1,釋放 1,當變數處於 0的情形下才可以被獲取。乙個執行緒的獲取可以用另乙個執行緒來釋放。很像二元訊號量,但是釋放只能是本執行緒。臨界區是比互斥量更加嚴格的同步手段,訊號量和互斥量可以不同程序之間操作,也就是說 乙個程序建立了乙個互斥量或訊號量,另乙個程序...
執行緒同步與鎖
為了避免多個執行緒對同乙個資料進行讀寫,我們要將各個執行緒進行同步。所謂同步,就是指在乙個執行緒訪問資料未結束的時候,其他執行緒不得對同一資料進行訪問。同步最常用的方法是鎖。是最簡單的一種鎖,只有兩種狀態 占用和非占用。她適合只能被唯一乙個執行緒獨佔訪問的資源。允許多個執行緒併發訪問的資源適合使用訊...
多執行緒同步與鎖
多執行緒同步與鎖 本次主要討論的是lock,autoeventset,moniter 如下 上圖為執行緒1,2執行write1,被阻塞,直到執行緒4發出訊號,執行緒1,2收到訊號後取得執行權的執行緒可以執行 改下main 上圖為執行緒3,5執行write2,執行緒4執行wirte4,首先取得lock...