0.序
1.基本概念
2.互斥量的例子
3.互斥量定義
3.1 64位系統(tǒng)
3.2 32位系統(tǒng)
3.3 pthread_mutex_t結(jié)構(gòu)的內(nèi)容
4.互斥量初始化與銷毀
4.1初始化
(1)靜態(tài)初始化
(2)動(dòng)態(tài)初始化
4.2銷毀互斥量
5.小結(jié)
0.序
本文涉及到的glibc版本為2.11,若無(wú)特別說(shuō)明,.表示glibc-2.11源代碼目錄,本文為/usr/src/glibc-2.11。
1.基本概念
臨界區(qū):一個(gè)存取共享資源的代碼段,而這些共享資源無(wú)法同時(shí)被多個(gè)線程訪問(wèn);即影響共享數(shù)據(jù)的代碼段。
線程同步方法
? ? ? ? ? ? ? ? ?確保對(duì)相同/相關(guān)數(shù)據(jù)的內(nèi)存訪問(wèn)互斥地進(jìn)行,即一次只能允許一個(gè)線程寫數(shù)據(jù),其他線程必須等待;
? ? ? ? ? ? ? ? ? Pthreads使用特殊形式的Edsger Dijkstra信號(hào)燈——互斥量;
? ? ? ? ? ? ? ? ? mutex: mutual(相互),exclusion(排斥);
2.互斥量的例子
下圖顯示了共享互斥量的三個(gè)線程的時(shí)序圖。

說(shuō)明
? ? ? ? ? ? ?處于標(biāo)圓形框之上的線段表示相關(guān)的線程沒(méi)有擁有互斥量;
? ? ? ? ? ? ?處于圓形框中心線之上的線段表示相關(guān)的線程等待互斥量;
? ? ? ? ? ? ?處于圓形框中心線之下的線段表示相關(guān)的線程擁有互斥量;
過(guò)程描述
? ? ? ? ? 最初,互斥量沒(méi)有被加鎖;
? ? ? ? ? 當(dāng)線程1試圖加鎖該互斥量時(shí),因?yàn)闆](méi)有競(jìng)爭(zhēng),線程1立即加鎖成功,對(duì)應(yīng)線段也移到中心線之下;
? ? ? ? ? 然后線程2試圖加鎖互斥量,由于互斥量已經(jīng)被加鎖,所以線程2被阻塞,對(duì)應(yīng)線段在中心線之上;
? ? ? ? ? 接著,線程1解鎖互斥量,于是線程2解除阻塞,并對(duì)互斥量加鎖成功;
? ? ? ? ? 然后,線程3試圖加鎖互斥量,同樣被阻塞;
? ? ? ? ?此時(shí),線程1調(diào)用函數(shù)pthread_mutext_trylock試圖加鎖互斥量,而立即返回EBUSY;
? ? ? ? ?然后,線程2解鎖互斥量,解除線程3的阻塞,線程3加鎖成功;
? ? ? ? ?最后,線程3完成工作,解鎖互斥量;
3.互斥量定義
3.1 64位系統(tǒng)
file: /usr/include/bits/pthreadtypes.h

該定義來(lái)自glibc,其在glibc代碼中的位置為./nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h。64位系統(tǒng)在安裝glibc的時(shí)候會(huì)自動(dòng)拷貝該文件(x86_64版本)到/usr/include/bits目錄。
其中,

關(guān)于__pthread_list_t(雙向鏈表)和__pthread_slist_t(單向鏈表)的定義可參考源代碼。
3.2 32位系統(tǒng)
file: /usr/include/bits/pthreadtypes.h

該定義來(lái)自glibc,其在glibc代碼中的位置為./nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h。32位系統(tǒng)在安裝glibc的時(shí)候會(huì)自動(dòng)拷貝該文件(i386版本)到/usr/include/bits目錄。
其中,

3.3 pthread_mutex_t結(jié)構(gòu)的內(nèi)容
如下是在64位系統(tǒng)的實(shí)驗(yàn)結(jié)果。

4.互斥量初始化與銷毀
4.1初始化
互斥量使用原則:使用前必須初始化,而且只被初始化一次;
(1)靜態(tài)初始化
使用宏P(guān)THREAD_MUTEX_INITIALIZER聲明具有默認(rèn)屬性的靜態(tài)互斥量;
file: /usr/include/pthread.h

該文件在glibc代碼中的位置為./nptl/sysdeps/pthread/pthread.h。
(2)動(dòng)態(tài)初始化
通過(guò)pthread_mutex_init()調(diào)用動(dòng)態(tài)初始化互斥量;
使用場(chǎng)合
? ? ? ? ? ? 當(dāng)使用malloc動(dòng)態(tài)分配一個(gè)包含互斥量的數(shù)據(jù)結(jié)構(gòu)時(shí),應(yīng)使用動(dòng)態(tài)初始化;
? ? ? ? ? ? 若要初始化一個(gè)非缺省屬性的互斥量,必須使用動(dòng)態(tài)初始化;
? ? ? ? ? ? 也可動(dòng)態(tài)初始化靜態(tài)聲明的互斥量,但必須保證每個(gè)互斥量在使用前被初始化,而且只能被初始化一次;
? ? ? ? ? ? 動(dòng)態(tài)初始化代碼可參考./nptl/pthread_mutex_init.c文件。其中__pthread_mutex_init()函數(shù)即對(duì)mutex的各個(gè)feild進(jìn)行初始化。
4.2銷毀互斥量
使用pthread_mutex_destroy()釋放互斥量。
注意
? ? ? ? ?當(dāng)確信沒(méi)有線程在互斥量上阻塞,且互斥量沒(méi)有被鎖住時(shí),可以立即釋放;
? ? ? ? ? 不需要銷毀一個(gè)使用PTHREAD_MUTEX_INITIALIZER宏靜態(tài)初始化的互斥量;
? ? ? ? ? 銷毀互斥量代碼可參考./nptl/pthread_mutex_destroy.c文件。其中__pthread_mutex_destroy()函數(shù)設(shè)置mutex的相應(yīng)字段使其不可用。代碼如下。

5小結(jié)
本文簡(jiǎn)單介紹互斥量的基本概念,如何初始化和銷毀及其注意問(wèn)題。后文分析其加鎖、解鎖原理。