轉自http://weihe6666.iteye.com/blog/1170141
條件變數是利用線程間共用的全域變數進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變數的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立訊號)。為了防止競爭,條件變數的使用總是和一個互斥鎖結合在一起。
一 pthread_cond_wait定義:
函數原型:int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
參數: cond 條件變數 mutex 互斥鎖
第一個參數*cond是指向一個條件變數的指標。第二個參數*mutex則是對相關的互斥鎖的指標。
二 pthread_cond_wait樣本理解
pthread_cond_wait的機制比較難裡理解,是條件變數中重要的成分。條件變數用於線程間同步,那麼pthread_cond_wait必須和互斥鎖同時作用在一個線程裡,它同時起到對資源的加鎖和解鎖,看下面的樣本:
程式建立了2個新線程使他們同步運行,實現進程t_b列印9以內3的倍數,t_a列印其他的數,程式開始線程t_b不滿足條件等待,線程t_a運行使a迴圈加1並列印。直到i為3的倍數時,線程t_a發送訊號通知進程t_b,這時t_b滿足條件,列印i值。
1 #include<pthread.h> 2 #include<unistd.h> 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/ 7 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//init cond 8 9 void *thread1(void*);10 void *thread2(void*);11 12 int i = 1; //global13 14 int main(void){15 pthread_t t_a;16 pthread_t t_b;//two thread17 18 pthread_create(&t_a,NULL,thread2,(void*)NULL);19 pthread_create(&t_b,NULL,thread1,(void*)NULL);//Create thread20 21 pthread_join(t_b,NULL);//wait a_b thread end22 pthread_mutex_destroy(&mutex);23 pthread_cond_destroy(&cond);24 exit(0);25 }26 27 void *thread1(void *junk){28 for(i = 1;i<= 9; i++){29 pthread_mutex_lock(&mutex); //互斥鎖30 printf("call thread1 \n");31 if(i%3 == 0)32 pthread_cond_signal(&cond); //send sianal to t_b33 else34 printf("thread1: %d\n",i);35 pthread_mutex_unlock(&mutex);36 sleep(1);37 }38 }39 40 void *thread2(void*junk){41 while(i < 9)42 {43 pthread_mutex_lock(&mutex);44 printf("call thread2 \n");45 if(i%3 != 0)46 pthread_cond_wait(&cond,&mutex); //wait47 printf("thread2: %d\n",i);48 pthread_mutex_unlock(&mutex);49 sleep(1);50 }51 }
View Code
輸出:
call thread2
call thread1
thread1: 1
call thread1
thread1: 2
call thread1
thread2: 3
call thread1
thread1: 4
call thread2
call thread1
thread1: 5
call thread1
thread2: 6
call thread1
thread1: 7
call thread2
call thread1
thread1: 8
call thread1
thread2: 9
樣本的解釋:
call thread2:是線程2即t_b首先上鎖,即
pthread_mutex_lock(&mutex);鎖住了mutex使得此進程執行線程2中的臨界區的代碼,當執行到45行:if(i%3
!= 0),此時i=1,滿足此條件,則執行46行: pthread_cond_wait(&cond,&mutex);
這句是關鍵,pthread_cond_wait(&cond,&mutex)操作有兩步,是原子操作:第一
解鎖,先解除之前的pthread_mutex_lock鎖定的mutex;第二
掛起,阻塞並在等待對列裡休眠,即線程2掛起,直到再次被喚醒,喚醒的條件是由pthread_cond_signal(&cond);發出的
cond訊號來喚醒。
call thread1:由於pthread_cond_wait已經對線程2解鎖,此時另外的線程只有線程1,那麼線程1對mutex上鎖,若這時有多個線程,那麼線程間上鎖的順序和作業系統有關。
thread1: 1:線程1上鎖後執行臨界區的代碼,當執行到if(i%3 ==
0)此時i=1,不滿足條件,則pthread_cond_signal(&cond);不被執行,那麼線程2仍處於掛起狀態,輸出
thread1: 1後線程1由pthread_mutex_unlock(&mutex);解鎖。
thread1:
2:這時此進程中只有2個線程,線程2處於掛起狀態,那麼只有線程1,則線程1又對mutex上鎖,此時同樣執行臨界區的代碼,而且i=2,不滿足條
件,pthread_cond_signal(&cond);不被執行,那麼線程2仍處於掛起狀態,輸出thread1:
1後線程1由pthread_mutex_unlock(&mutex);解鎖。
call
thread1:同樣由線程1上鎖,但此時i=3,滿足條件pthread_cond_signal(&cond)被執行,那麼
pthread_cond_signal(&cond)會發出訊號,來喚醒處於掛起的線程2。pthread_cond_signal同樣由兩個
原子操作:1,解鎖;2,發送訊號;解鎖即對線程1解鎖,解除對mutex的上鎖。發送訊號,即給等待signal掛起的線程2發送訊號,喚醒掛起的線程
2。
thread2:
3:由於pthread_cond_signal喚醒了線程2,即i=3滿足條件,pthread_cond_wait(&cond,&
mutex);被執行,那麼pthread_cond_wait(&cond,&mutex)此時也有一步操作:上鎖;即對線程2上鎖,
此時的pthread_cond_wait(&cond,&mutex)的操作相當與
pthread_mutex_lock(&mutex);那麼線程2繼續執行上鎖後的臨界區的代碼,並由
pthread_mutex_unlock(&mutex);對線程2進行解鎖。
剩下的輸出原理和上面解釋的一樣。
縱觀pthread_cond_wait,它的理解不可之把它看作一個簡單的wait函數,它裡面應該是一族函數,不同的函數在不同的條件下執行,理解pthread_cond_wait的機制可以很好的學習條件變數。