當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 線程互斥與同步
一、線程間互斥
1.互斥鎖
1) 引入互斥(mutual exclusion)鎖的目的是用來保證共享數(shù)據(jù)操作的完整性;
2) 互斥鎖主要用來保護(hù)臨界資源;
3) 每個(gè)臨界資源都由一個(gè)互斥鎖來保護(hù),任何時(shí)刻多只能有一個(gè)線程能訪問該資源;
4) 線程必須先獲得互斥鎖才能訪問臨界資源,訪問完資源后釋放該鎖。如果無(wú)法獲得鎖,線程會(huì)阻塞直到獲得鎖為止。
2.互斥鎖API:
設(shè)置鎖:初始化鎖
第一個(gè)參數(shù)是變量的地址,
第二個(gè)參數(shù)是互斥鎖的屬性。
上鎖:
解鎖:
拓展:pthread_mutex_destroy 刪除鎖。
pthread_mutex_trylock()試圖加鎖函數(shù)。
3.示例代碼
一定會(huì)將加鎖與解鎖中的所以的動(dòng)作完成后,下一個(gè)申請(qǐng)才會(huì)開始。保證數(shù)據(jù)的原子性。
比如兩個(gè)線程同時(shí)操作日志文件。讀寫操作的結(jié)果可能被打斷,結(jié)果是未知的。
互斥鎖過程回顧:
定義鎖變量 //買一把鎖,(全局變量)
初始化鎖 //設(shè)置鎖狀態(tài)
對(duì)臨界資源加鎖 //上鎖
臨界資源代碼
對(duì)臨界資源解鎖 //解鎖
二、同步與信號(hào)量
1.什么是同步
互斥表示的是兩者不能同時(shí)對(duì)臨界資源進(jìn)行操作,先后順序沒有任何保證,哪個(gè)線程擁有時(shí)間片,哪個(gè)線程就進(jìn)行臨界資源訪問。相當(dāng)于兩個(gè)操作之間是相互排斥的,必須保證一個(gè)線程訪問結(jié)束,另一個(gè)線程才可以進(jìn)行訪問資源。(訪問互斥,無(wú)序,當(dāng)一個(gè)線程加鎖之后,必須等當(dāng)前線程的臨界資源訪問代碼執(zhí)行結(jié)束之后,執(zhí)行了解鎖代碼,才會(huì)釋放了鎖!)
同步也是不可以同時(shí)運(yùn)行(同時(shí)訪問臨界資源),同步是在互斥的基礎(chǔ)上按照一定的順序進(jìn)程訪問資源。同步在互斥的基礎(chǔ)上,加入一定的機(jī)制保證資源訪問的順序。(訪問互斥,有序)。
2.信號(hào)量的提出
實(shí)現(xiàn)同步的功能提出信號(hào)量的概念。在現(xiàn)實(shí)生活中,交通路口的紅綠燈就是一種同步,有紅綠兩種等,紅燈亮,則綠燈滅。紅燈滅,則綠燈亮。
紅燈狀態(tài): 1 --> 0
綠燈狀態(tài): 0 --> 1
信號(hào)量表示資源的數(shù)量,當(dāng)綠燈狀態(tài)為1,表示綠色方向的道路資源可用,可以通行后,綠燈再減1變成0。
資源的數(shù)量可以是多個(gè),即信號(hào)量的數(shù)量可以大于1,比如公司PC的數(shù)量就是一種資源,可以有N臺(tái)PC供員工申請(qǐng)?jiān)囉,申?qǐng)成功就要將資源的數(shù)量減1,當(dāng)有員工返還PC時(shí),資源的數(shù)據(jù)加1。
P/V操作:
3.有名信號(hào)與無(wú)名信號(hào)的比較
1) 有名信號(hào)量必須指定一個(gè)相關(guān)聯(lián)的文件名稱,這個(gè)name通常是文件系統(tǒng)中的某個(gè)文件;無(wú)名信號(hào)量不需要指定名稱。
2) 有名信號(hào)量既可用于線程間的同步,又能用于進(jìn)程間的同步;無(wú)名信號(hào)量通過shared參數(shù)來決定是進(jìn)程內(nèi)還是相關(guān)進(jìn)程間共享。
3) 有名信號(hào)量是隨內(nèi)核持續(xù)的,一個(gè)進(jìn)程創(chuàng)建一個(gè)信號(hào)量,另外的進(jìn)程可以通過該信號(hào)量的外部名(創(chuàng)建信號(hào)量使用的文件名)來訪問它。進(jìn)程結(jié)束后,信號(hào)量還存在,并且信號(hào)量的值也不會(huì)改動(dòng)。
4) 無(wú)名信號(hào)量的持續(xù)性卻是不定的:如果無(wú)名信號(hào)量是由單個(gè)進(jìn)程內(nèi)的各個(gè)線程共享的,那么該信號(hào)量就是隨進(jìn)程持續(xù)的,當(dāng)該進(jìn)程終止時(shí)它也會(huì)消失。如果某個(gè)無(wú)名信號(hào)量是在不同進(jìn)程間同步的,該信號(hào)量必須存放在共享內(nèi)存區(qū)中,只要該共享內(nèi)存區(qū)存在,該信號(hào)量就存在。
5) 無(wú)名信號(hào)量(文件系統(tǒng)不可見,內(nèi)存信號(hào)量)。
信號(hào)量是一個(gè)受保護(hù)的變量,不可以隨意操作,由相應(yīng)的函數(shù)操作。
4.pthreaad庫(kù)常用的信號(hào)量操作函數(shù)如下:
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem); //P操作
int sem_post(sem_t *sem); //V操作
int sem_trywait(sem_t *sem);
int sem_getvalue(sem_t *sem, int *svalue);
pshared: 信號(hào)量共享范圍,0是線程間使用。非0表示進(jìn)程間使用(不過函數(shù)并沒有對(duì)進(jìn)程間無(wú)名信號(hào)支持, 設(shè)想總是好的嗎).
value: 資源的個(gè)數(shù)。
sem_wait() 信號(hào)量減一
sem_post() 信號(hào)量加一
sem_trywait() 不阻塞的方式P申請(qǐng)。
setm_getvalue() 獲取當(dāng)前信號(hào)量的個(gè)數(shù),保存在第二個(gè)參數(shù)中。
5.示例代碼
1) 信號(hào)量實(shí)現(xiàn)互斥:
2) 信號(hào)量實(shí)現(xiàn)同步
3) 鎖實(shí)現(xiàn)同步:
PS:
1. 鎖是信號(hào)量數(shù)量為1時(shí)的一種特殊情況,即鎖也可以看成一種信號(hào)量。
2. 互斥的實(shí)現(xiàn)要用到一個(gè)鎖變量或一個(gè)信號(hào)量。
3. 同步要用到至少兩把鎖或兩個(gè)信號(hào)量。
思考:
如果三個(gè)線程,如果實(shí)現(xiàn)同步(即pthread1, pthread2 pthread3按照順序執(zhí)行)?