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