1、 mutex互斥量多線程
同步:就是對資源的訪問有序。互斥:就是任一時刻來講只有一個在執行;可是對於多線程的程序來講,訪問衝突的問題是很廣泛的,解決的辦法是引入互斥鎖(Mutex,MutualExclusive Lock),得到鎖的線程能夠完成「讀-修改-寫」的操做,而後釋放鎖給其它線程,沒有得到鎖的線程只能等待而不能訪問共享數據,這樣「讀-修改-寫」三步操做組成一個原子操做,要麼都執行,要麼都不執行,不會執行到中間被打斷,也不會在其它處理器上並行作這個操做。ide
互斥鎖用pthread_mutex_t類型的變量表示。用pthread_mutex_init初始化,用hread_destory()銷燬。成功返回0,失敗返回錯誤號。。若是Mutex變量是靜態分配的(全局變量 或static變量),也能夠用宏定義PTHREAD_MUTEX_INITIALIZER來初始化,至關於用pthread_mutex_init初始化而且attr參數爲NULL函數
一個線程能夠調用pthread_mutex_lock得到Mutex,若是這時另外一個線程已經調pthread_mutex_lock得到了該Mutex,則當前線程須要掛起等待,直到另外一個線程調用pthread_mutex_unlock釋放Mutex,當前線程被喚醒,才能得到該Mutex並繼續執行。意思就是說若是有一個線程對mutex上了鎖,沒有開鎖,另一個線程想得到mutex,就得掛機等待,直到上鎖的線程開了鎖釋放開mutex以後,該線程被喚醒,才能得到mutex.spa
若是一個線程既想得到鎖,又不想掛起等待,能夠調用pthread_mutex_trylock,若是Mutex已經被另外一個線程得到,這個函數會失敗返回EBUSY,而不會使線程掛起等待。線程
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<pthread.h> 4 static int g_count=0; 5 void * addWrite(void * arg) 6 { 7 int count=0; 8 int value=0; 9 while(count++ <5000) 10 { 11 value=g_count; 12 printf("g_count is %d\n",g_count); 13 g_count=value+1; 14 } 15 } 16 int main() 17 { 18 pthread_t id1; 19 pthread_t id2; 20 int ret=pthread_create(&id1,NULL,addWrite,NULL); 21 int res=pthread_create(&id2,NULL,addWrite,NULL); 22 pthread_join(id1,NULL); 23 pthread_join(id2,NULL);
咱們建立兩個線程,各自把g_count增長5000次,正常狀況下最後counter應該等於10000,但事實上每次運行該程序的結果都不同,有時候數到5000多,有時候數到6000多可是加上鎖以後(在)第五行加上pthread_mutex_init 以下圖blog
結果:進程
加上鎖以後,就輸出10000內存
2、lock和unlock的實現原理
資源
爲了實現互斥鎖操做,大多數體系結構都提供了swap或exchange指令,該指令的做用是把寄存器和內存單元的數據相交換,因爲只有一條指令,保證了原子性,即便是多處理器平臺,訪問內存的總線週期也有前後,一個處理器上的交換指令執行時另外一個處理器的交換指令只能等待總線週期。以下圖的僞代碼所示。unlock中的釋放鎖操做一樣只用一條指令實現,以保證它的原子性。get
3、死鎖
·通常狀況下,若是同一個線程前後兩次調用lock,在第二次調用時,因爲鎖已經被佔用,該線程會掛起等待別的線程釋放鎖,然而鎖正是被本身佔用着的,該線程又被掛起而沒有機會釋放鎖,所以 就永遠處於掛起等待狀態了,這叫作死鎖(Deadlock)。另外一種典型的死鎖情形是這樣:線程A得到了鎖1,線程B得到了鎖2,這時線程A調用lock試圖得到鎖2,結果是須要掛起等待線程B釋放鎖2,而這時線程B也調用lock試圖得到鎖1,結果是須要掛起等待線程A釋放鎖1,因而線程A和B都永遠處於掛起狀態了。
死鎖造成的條件
①、互斥條件:一個資源每次只能被一個線程使用。
②、請求與保持條件:一個進程因請求資源而被阻塞時,對已得到的資源保持不放。
③、不剝奪條件:進程已得到的資源,在未使用完以前,不能強行剝奪。
④循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係
若是涉及到更多的線程和更多的鎖,則更容易引發死鎖問題。寫程序時應該儘可能避免同時得到多個鎖,若是必定有必要這麼作,則有一個原則:若是全部線程在須要多個鎖時都按相同的前後順序(常見的是按Mutex變量的地址順序)得到鎖,則不會出現死鎖。好比一個程序中用到鎖一、鎖二、鎖3,它們所對應的Mutex變量的地址是鎖1<鎖2<鎖3,那麼 全部線程在須要同時得到2個或3個鎖時都應該按鎖一、鎖二、鎖3的順序得到。若是要爲全部的鎖肯定一個前後順序比較困難,則應該儘可能使用pthread_mutex_trylock調用代替pthread_mutex_lock調用,以避免死鎖。