淺析pthread_cond_wait(轉)


轉自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 }                                    
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的機制可以很好的學習條件變量。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM