(轉載)pThreads線程(二) 線程同步--互斥量/鎖

  互斥量(Mutex)是「mutual exclusion」的縮寫。互斥量是實現線程同步,和保護同時寫共享數據的主要方法。
  互斥量對共享數據的保護就像一把鎖。在Pthreads中,任什麼時候候僅有一個線程能夠鎖定互斥量,所以,當多個線程嘗試去鎖定該互斥量時僅有一個會成功。直到鎖定互斥量的線程解鎖互斥量後,其餘線程才能夠去鎖定互斥量。線程必須輪着訪問受保護數據。
  一個擁有互斥量的線程常常用於更新全局變量。確保了多個線程更新一樣的變量以安全的方式運行,最終的結果和一個線程處理的結果是相同的。這個更新的變量屬於一個「臨界區(critical section)」。
html


  使用互斥量的典型順序以下:
程序員

  • 建立和初始一個互斥量
  • 多個線程嘗試去鎖定該互斥量
  • 僅有一個線程能夠成功鎖定改互斥量
  • 鎖定成功的線程作一些處理
  • 線程解鎖該互斥量
  • 另一個線程得到互斥量,重複上述過程
  • 最後銷燬互斥量

  當多個線程競爭同一個互斥量時,失敗的線程會阻塞在lock調用處。能夠用「trylock」替換「lock」,則失敗時不會阻塞。當保護共享數據時,程序員有責任去確認是否須要使用互斥量。如,若四個線程會更新一樣的數據,但僅有一個線程用了互斥量,則數據可能會損壞。安全

 

 

建立和銷燬互斥量:

pthread_mutex_init (mutex,attr)  
pthread_mutex_destroy (mutex)  
pthread_mutexattr_init (attr)  
pthread_mutexattr_destroy (attr) 

用法函數

互斥量必須用類型pthread_mutex_t類型聲明,在使用前必須初始化,這裏有兩種方法能夠初始化互斥量:
聲明時靜態地,如: pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
動態地用pthread_mutex_init()函數,這種方法容許設定互斥量的屬性對象attr。
互斥量初始化後是解鎖的。
attr對象用於設置互斥量對象的屬性,使用時必須聲明爲pthread_mutext_attr_t類型,默認值能夠是NULL。Pthreads標準定義了三種可選的互斥量屬性:
post

  • 協議(Protocol): 指定了協議用於阻止互斥量的優先級改變
  • 優先級上限(Prioceiling):指定互斥量的優先級上限
  • 進程共享(Process-shared):指定進程共享互斥量

注意全部實現都提供了這三個可先的互斥量屬性。
pthread_mutexattr_init()和pthread_mutexattr_destroy()函數分別用於建立和銷燬互斥量屬性對象。
pthread_mutex_destroy()應該用於釋放不須要再使用的互斥量對象。
url

鎖定和解鎖互斥量:

函數spa

pthread_mutex_lock (mutex)  
pthread_mutex_trylock (mutex)  
pthread_mutex_unlock (mutex)  

用法線程

線程用pthread_mutex_lock()函數去鎖定指定的mutex變量,若該mutex已經被另一個線程鎖定了,該調用將會阻塞線程直到mutex被解鎖。
pthread_mutex_trylock() will attempt to lock a mutex. However, if the mutex is already locked, the routine will return immediately with a "busy" error code. This routine may be useful in pthread_mutex_trylock().
code

  嘗試着去鎖定一個互斥量,然而,若互斥量已被鎖定,程序會馬上返回並返回一個忙錯誤值。該函數在優先級改變狀況下阻止死鎖是很是有用的。線程能夠用pthread_mutex_unlock()解鎖本身佔用的互斥量。在一個線程完成對保護數據的使用,而其它線程要得到互斥量在保護數據上工做時,能夠調用該函數。如有一下情形則會發生錯誤:htm

  • 互斥量已經被解鎖
  • 互斥量被另外一個線程佔用

互斥量並無多麼「神奇」的,實際上,它們就是參與的線程的「君子約定」。寫代碼時要確信正確地鎖定,解鎖互斥量。
Q:有多個線程等待同一個鎖定的互斥量,當互斥量被解鎖後,那個線程會第一個鎖定互斥量?
A:除非線程使用了優先級調度機制,不然,線程會被系統調度器去分配,那個線程會第一個鎖定互斥量是隨機的。

用例: 

 1 #include<stdlib.h>  
 2 #include<stdio.h>  3 #include<unistd.h>  4 #include<pthread.h>  5  6 typedef struct ct_sum  7 {  8 int sum;  9 pthread_mutex_t lock; 10 }ct_sum; 11 12 void * add1(void *cnt) 13 { 14 pthread_mutex_lock(&(((ct_sum*)cnt)->lock)); 15 for(int i=0; i < 50; i++) 16  { 17 (*(ct_sum*)cnt).sum += i; 18  } 19 pthread_mutex_unlock(&(((ct_sum*)cnt)->lock)); 20  pthread_exit(NULL); 21 return 0; 22 } 23 void * add2(void *cnt) 24 { 25 pthread_mutex_lock(&(((ct_sum*)cnt)->lock)); 26 for(int i=50; i<101; i++) 27  { 28 (*(ct_sum*)cnt).sum += i; 29  } 30 pthread_mutex_unlock(&(((ct_sum*)cnt)->lock)); 31  pthread_exit(NULL); 32 return 0; 33 } 34 35 int main(void) 36 { 37  pthread_t ptid1, ptid2; 38  ct_sum cnt; 39 pthread_mutex_init(&(cnt.lock), NULL); 40 cnt.sum=0; 41 42 pthread_create(&ptid1, NULL, add1, &cnt); 43 pthread_create(&ptid2, NULL, add2, &cnt); 44 45  pthread_join(ptid1,NULL); 46  pthread_join(ptid2,NULL); 47 48 printf("sum %d\n", cnt.sum); 49 pthread_mutex_destroy(&(cnt.lock)); 50 51 return 0; 52 } 

 

原文地址:http://www.cnblogs.com/dongsheng/p/4186358.html

相關文章
相關標籤/搜索