轉自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; //global 13 14 int main(void){ 15 pthread_t t_a; 16 pthread_t t_b;//two thread 17 18 pthread_create(&t_a,NULL,thread2,(void*)NULL); 19 pthread_create(&t_b,NULL,thread1,(void*)NULL);//Create thread 20 21 pthread_join(t_b,NULL);//wait a_b thread end 22 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_b 33 else 34 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); //wait 47 printf("thread2: %d\n",i); 48 pthread_mutex_unlock(&mutex); 49 sleep(1); 50 } 51 }
輸出:
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的機制可以很好的學習條件變量。