線程互(hu)斥(chi)與同(tong)步(bu)
時間:2018-09-29 來源(yuan):未知
一、線程間互斥(chi)
1.互斥鎖
1) 引(yin)入(ru)互斥(mutual exclusion)鎖的(de)目的(de)是用(yong)來保證共享數據操作的(de)完整性(xing);
2) 互斥(chi)鎖主要用來保護臨界資源;
3) 每(mei)個臨界資源都由一(yi)個互斥鎖來(lai)保護,任何時刻多只能有一(yi)個線程(cheng)能訪問該(gai)資源;
4) 線程必須先獲得互斥(chi)鎖才能訪問臨(lin)界資源,訪問完資源后(hou)釋(shi)放該鎖。如果無法(fa)獲得鎖,線程會阻(zu)塞直到獲得鎖為止。
2.互斥鎖(suo)API:
設置鎖:初始化鎖

第一個參數是變(bian)量的(de)地址(zhi),
第二個參數是互斥(chi)鎖的屬性。
上鎖:

解鎖:

拓展:pthread_mutex_destroy 刪除鎖。
pthread_mutex_trylock()試圖加(jia)鎖函數。
3.示例(li)代碼(ma)


一(yi)定會將(jiang)加鎖與解鎖中(zhong)的所(suo)以(yi)的動作(zuo)完(wan)成后,下一(yi)個申(shen)請(qing)才會開(kai)始。保證數據的原(yuan)子性。
比如兩個(ge)線程(cheng)同時操作日志文件。讀寫操作的結(jie)果可能被打斷,結(jie)果是未知的。
互斥鎖過程回顧:
定義鎖變量 //買一(yi)把鎖,(全局變量)
初始化鎖 //設置鎖狀態
對臨界資源加鎖 //上鎖
臨界資源代碼
對臨界資源解鎖 //解鎖
二、同步與(yu)信號量
1.什么是同步
互(hu)斥(chi)表示的(de)是(shi)兩(liang)者不能同時對臨(lin)界(jie)資源進行(xing)操(cao)作(zuo),先后順序(xu)沒有(you)任何保證,哪個線(xian)程擁有(you)時間片(pian),哪個線(xian)程就進行(xing)臨(lin)界(jie)資源訪(fang)問(wen)。相(xiang)當于兩(liang)個操(cao)作(zuo)之間是(shi)相(xiang)互(hu)排(pai)斥(chi)的(de),必須保證一個線(xian)程訪(fang)問(wen)結(jie)束(shu)(shu),另一個線(xian)程才可以進行(xing)訪(fang)問(wen)資源。(訪(fang)問(wen)互(hu)斥(chi),無(wu)序(xu),當一個線(xian)程加鎖(suo)之后,必須等當前線(xian)程的(de)臨(lin)界(jie)資源訪(fang)問(wen)代碼執行(xing)結(jie)束(shu)(shu)之后,執行(xing)了解(jie)鎖(suo)代碼,才會(hui)釋放了鎖(suo)!)
同步(bu)也(ye)是不可(ke)以同時運行(同時訪問(wen)臨界資(zi)源),同步(bu)是在互斥(chi)(chi)的基礎(chu)上按照一定的順序進(jin)程訪問(wen)資(zi)源。同步(bu)在互斥(chi)(chi)的基礎(chu)上,加入一定的機制保證(zheng)資(zi)源訪問(wen)的順序。(訪問(wen)互斥(chi)(chi),有序)。
2.信號(hao)量的提出
實(shi)現同步(bu)的功能提出信(xin)號(hao)量的概念。在(zai)現實(shi)生(sheng)活中,交通路(lu)口的紅綠燈(deng)(deng)(deng)就(jiu)是一種(zhong)(zhong)同步(bu),有紅綠兩種(zhong)(zhong)等,紅燈(deng)(deng)(deng)亮,則(ze)綠燈(deng)(deng)(deng)滅。紅燈(deng)(deng)(deng)滅,則(ze)綠燈(deng)(deng)(deng)亮。
紅燈(deng)狀態(tai): 1 --> 0
綠燈狀(zhuang)態: 0 --> 1
信號量(liang)表示(shi)資(zi)源(yuan)的數(shu)量(liang),當綠(lv)燈狀態為1,表示(shi)綠(lv)色方(fang)向的道路資(zi)源(yuan)可用,可以通行后(hou),綠(lv)燈再減1變成(cheng)0。
資源的數量(liang)可以(yi)是多個,即信號量(liang)的數量(liang)可以(yi)大于1,比如公司PC的數量(liang)就是一種資源,可以(yi)有N臺PC供員工申請(qing)試用(yong),申請(qing)成功就要(yao)將資源的數量(liang)減1,當有員工返還PC時,資源的數據加1。

P/V操作:

3.有名信號(hao)與(yu)無(wu)名信號(hao)的比較
1) 有(you)名信號量必須指(zhi)定一個(ge)相關聯(lian)的(de)文件(jian)名稱,這個(ge)name通常是文件(jian)系統(tong)中的(de)某個(ge)文件(jian);無名信號量不需要指(zhi)定名稱。
2) 有名(ming)信號量既可用于(yu)線程(cheng)間的同步(bu),又能用于(yu)進(jin)程(cheng)間的同步(bu);無(wu)名(ming)信號量通過shared參數來決定是進(jin)程(cheng)內還是相關進(jin)程(cheng)間共享。
3) 有(you)名(ming)信(xin)號(hao)量(liang)是隨(sui)內核持續的(de),一(yi)個進程創(chuang)建(jian)一(yi)個信(xin)號(hao)量(liang),另外的(de)進程可以通(tong)過該(gai)信(xin)號(hao)量(liang)的(de)外部(bu)名(ming)(創(chuang)建(jian)信(xin)號(hao)量(liang)使用(yong)的(de)文件名(ming))來訪問它。進程結束后,信(xin)號(hao)量(liang)還存在(zai),并且信(xin)號(hao)量(liang)的(de)值也不會改(gai)動。
4) 無名(ming)(ming)信號(hao)(hao)量的(de)持續(xu)性卻是不定(ding)的(de):如果(guo)無名(ming)(ming)信號(hao)(hao)量是由(you)單個(ge)進程(cheng)內(nei)的(de)各個(ge)線(xian)程(cheng)共享的(de),那(nei)么該(gai)信號(hao)(hao)量就是隨進程(cheng)持續(xu)的(de),當(dang)該(gai)進程(cheng)終止(zhi)時它也會消失(shi)。如果(guo)某個(ge)無名(ming)(ming)信號(hao)(hao)量是在不同進程(cheng)間(jian)同步(bu)的(de),該(gai)信號(hao)(hao)量必須存(cun)(cun)(cun)放在共享內(nei)存(cun)(cun)(cun)區中,只要該(gai)共享內(nei)存(cun)(cun)(cun)區存(cun)(cun)(cun)在,該(gai)信號(hao)(hao)量就存(cun)(cun)(cun)在。
5) 無名信號(hao)量(文件系統不可見,內存信號(hao)量)。
信號量是一(yi)個受保(bao)護的變量,不(bu)可(ke)以隨意操(cao)作,由相應(ying)的函(han)數操(cao)作。
4.pthreaad庫常用(yong)的信(xin)號量(liang)操(cao)作函數如下:
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem); //P操作(zuo)
int sem_post(sem_t *sem); //V操作
int sem_trywait(sem_t *sem);
int sem_getvalue(sem_t *sem, int *svalue);

pshared: 信號量共享范圍(wei),0是線(xian)程(cheng)(cheng)間(jian)使用。非0表示進(jin)程(cheng)(cheng)間(jian)使用(不過函數(shu)并(bing)沒有(you)對進(jin)程(cheng)(cheng)間(jian)無(wu)名信號支持, 設(she)想總(zong)是好的嗎).
value: 資源的個數。

sem_wait() 信號量減一
sem_post() 信號量加一
sem_trywait() 不阻塞的方式P申請。
setm_getvalue() 獲取當(dang)前信號量的個(ge)數,保(bao)存在第二個(ge)參數中。
5.示例代碼
1) 信號量實現互斥:


2) 信號量實現同步


3) 鎖實現同步:


PS:
1. 鎖是信號量數(shu)量為1時(shi)的(de)一(yi)(yi)種(zhong)特殊情況,即(ji)鎖也(ye)可(ke)以看成(cheng)一(yi)(yi)種(zhong)信號量。
2. 互(hu)斥的實(shi)現要(yao)用到一(yi)個(ge)(ge)鎖變量或一(yi)個(ge)(ge)信(xin)號量。
3. 同(tong)步要用到至少兩(liang)把鎖或兩(liang)個(ge)信(xin)號量。
思考:
如果三個線程,如果實現同步(bu)(即pthread1, pthread2 pthread3按照順序(xu)執(zhi)行)?

