【C/C++多執行緒程式設計之八】pthread條件變數

Love_Hulidear發表於2014-05-03

多執行緒程式設計之條件變數


     Pthread是 POSIX threads 的簡稱,是POSIX的執行緒標準
        互斥機制,包括互斥量【C/C++多執行緒程式設計之六】pthread互斥量,訊號量【C/C++多執行緒程式設計之七】pthread訊號量,互斥能很好的處理共享資源訪問的協調問題,是多執行緒同步必不可少的機制。互斥機制也有其缺陷,當執行緒在等待共享資源滿足某個條件,互斥機制下,必須不斷地加鎖和解鎖,其間查詢共享資源是否滿足條件,這將帶來巨大的消耗。
        此時,需要新的機制來解決這個問題。

       1.條件變數機制:

        條件變數機制彌補了互斥機制的缺陷,允許一個執行緒向另一個執行緒傳送訊號(這意味著共享資源某種條件滿足時,可以通過某個執行緒發訊號的方式通知等待的執行緒),允許阻塞等待執行緒(當執行緒等待共享資源某個條件時,可讓該執行緒阻塞,等待其他執行緒傳送訊號通知)。
        條件變數機制在處理等待共享資源滿足某個條件問題時,具有非常高的效率,且空間消耗相比互斥機制也有優勢。
    
        2.條件變數與互斥量:

       條件變數機制,所有等待一個條件變數的執行緒會形成一個佇列,這個佇列顯然是全域性的共享佇列。當執行緒進入等待狀態,將執行緒新增到佇列就需要使用互斥量,防止多個執行緒同時使用pthread_cond_wait,在呼叫pthread_cond_wait前加鎖互斥量,進入阻塞前解鎖互斥量。這也解釋了pthread_cond_wait函式引數需要互斥量。

        3.條件變數基本函式:
         #include <semaphore.h>
初始化條件變數:
        int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) ;
        該函式第一個引數為條件變數指標,第二個引數為條件變數屬性指標(一般設為NULL)。該函式按照條件變數屬性對條件變數程式初始化。
無條件等待:
        int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
        該函式第一個引數為條件變數指標,第二個為互斥量指標。該函式呼叫前,需本執行緒加鎖互斥量,加鎖狀態的時間內函式完成執行緒加入等待佇列操作 ,執行緒進入等待前函式解鎖互斥量。在滿足條件離開pthread_cond_wait函式之前重新獲得互斥量並加鎖,因此,本執行緒之後需要再次解鎖互斥量。
通知一個執行緒:
        int pthread_cond_signal(pthread_cond_t *cond);
        該函式的引數為條件變數指標。該函式向佇列第一個等待執行緒傳送訊號,解除這個執行緒的阻塞狀態。
通知所有執行緒:
        int pthread_cond_broadcast(pthread_cond_t *cond);
        該函式的引數為條件變數指標。該函式想佇列所有等待執行緒傳送訊號,解除這些執行緒的阻塞狀態。
銷燬條件變數:
        int pthread_cond_destroy(pthread_cond_t *cond);
        該函式銷燬條件變數。

        4.牛刀小試
         共享資源i,執行緒1對i進行無限加1操作,並輸出所有非5倍數的i值。當i的值為5的倍數時,通過條件變數機制,通知執行緒2,執行緒2輸出此時的i值。
#include 
#include 
#include 
#include 
#pragma comment(lib, "pthreadVC2.lib")     //必須加上這句
pthread_t t1;           //pthread_t變數t1,用於獲取執行緒1的ID
pthread_t t2;           //pthread_t變數t2,用於獲取執行緒2的ID       
pthread_mutex_t mutex;
pthread_cond_t cond;
int i=0;                //共享資源
void * child1(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		i++;
		if(i%5==0)
		{
			pthread_cond_signal(&cond);
		}
		else
		{
			printf("我是執行緒  1  列印的數都非5的倍數:  %d \n",i);
		}
		pthread_mutex_unlock(&mutex);
		Sleep(1000);
	}
}      
void *child2(void *arg)
{
    while(1)
	{
		pthread_mutex_lock(&mutex);
		pthread_cond_wait(&cond,&mutex);       //獲得訊號之前,會重新獲得互斥鎖
		printf("我是執行緒  2  列印5的倍數:  %d \n",i);
		pthread_mutex_unlock(&mutex);          //需要在此處釋放互斥鎖
		Sleep(1000);
	}
}
int main(void)
{
       
        pthread_cond_init(&cond,NULL);
		pthread_mutex_init(&mutex,NULL); 
        pthread_create(&t1,NULL,child1,NULL);
        pthread_create(&t2,NULL,child2,NULL);
        Sleep(100000000);
       
}
             



相關文章