線程同步2 ------ 條件變量

      條件變量是利用線程間共享的全局變量進行同步的一種機制。條件變量宏觀上類似if語句,符合條件就能執行某段程序,否則只能等待條件成立。

      使用條件變量主要包括2個動作:一個等待使用資源的線程“等待條件變量被設置爲真”;另一個線程在使用完資源後“設置條件爲真”,這樣就可以保證線程間的同步了。那麼關鍵的問題來了,就是要保證條件變量能被正確地修改,條件變量應該得到特殊的保護。實際使用中其實仍然需要用到互斥鎖,互斥鎖充當了這樣一個保護者的角色。


      條件變量的典型應用場景,是處理類似於如下特定情形的線程同步問題:

  1. 若干個線程在某個條件沒有滿足時不能繼續往下運行,紛紛調用pthread_cond_wait使自己在這個條件上陷入等待(休眠)。
  2. 當條件滿足後,提供任務的線程(即活躍着的)調用pthread_cond_broadcast(或pthread_cond_signal)通知(喚醒)剛纔那些等待在這個條件上的所有線程,讓它們繼續往下運行。
  3. 實際應用場景中,通常希望每調用一次pthread_cond_signal就喚醒一個等待線程。比如,某線程專門負責從網絡接收數據包,其他若干線程專門負責處理數據包。當沒有數據包時,處理線程全部調用pthread_cond_wait陷入等待。當一個數據包到達時,接收線程調用pthread_cond_signal喚醒一個處理線程來處理數據包。新的數據包到來時,接收線程再次調用pthread_cond_signal喚醒一個線程。


操作條件變量的函數

pthread_cond_init 初始化條件變量
pthread_cond_wait 基於條件變量阻塞,無條件等待
pthread_cond_timedwait 阻塞直到指定事件發生,計時等待
pthread_cond_signal 解除特定線程的阻塞,存在多個等待線程時按入隊順序激活其中一個
pthread_cond_broadcast 解除所有線程的阻塞
pthread_cond_destroy 清除條件變量
   


      條件變量的初始化,也有2種:

  1. 靜態賦值法,將宏結構常量PTHREAD_COND_INITIALIZER賦予互斥鎖:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  2. 使用函數pthread_cond_init,其原型如下。其中cond_attr是條件變量的屬性,通常設置爲NULL。

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

      等待條件成立有2個函數:pthread_cond_wait和pthread_cond_timedwait。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

      上述2個函數用法類似,函數將阻塞直到條件變量獲得信號。區別是後者增添了一個超時abstime,如果在給定時限前條件仍未滿足,則返回ETIMEOUT,解除阻塞,結束等待。

C語言互斥鎖-條件變量的一個實例 ------ C語言互斥鎖---條件變量實現公共緩存區數據讀寫:

《注:以下程序實例引用自:http://blog.csdn.net/android_hasen/article/details/9735721。這個實例放到這裏說明條件變量的基本用法再合適不過了!!!》

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <error.h>  
#include <fcntl.h>  
#include <unistd.h>  
#include <pthread.h>  
  
char buffer[128];   
int has_data=0;  
pthread_mutex_t mutex;  
pthread_cond_t cond;  
pthread_cond_t cond2;  
  
void read_buf(void)  
{  
    do  
    {  
        pthread_mutex_lock(&mutex);//鎖定互斥鎖  
        if(has_data==0)  
        {  
            /*阻塞線程,等待另外一個線程發送信號,同時爲公共數據區解鎖*/  
            pthread_cond_wait(&cond,&mutex);  
        }  
        else if(has_data==1)  
        {  
            printf("the data : %s\n",buffer);  
            has_data=0;  
            pthread_cond_signal(&cond2);  
        }  
        pthread_mutex_unlock(&mutex);//打開互斥鎖  
    }while(strcmp(buffer,"#")!=0);  
    pthread_exit(NULL);  
}  
  
void write_buf(void)  
{  
    char input[128];  
    do  
    {  
        pthread_mutex_lock(&mutex);  
        if(has_data==0)  
        {  
            memset(input,'\0',128);  
            printf("input data:\t");  
            scanf("%s",input);  
            sprintf(buffer,"%s",input);  
            has_data=1;  
            pthread_cond_signal(&cond);//條件改變,喚醒阻塞的線程  
          
        }  
        else if(has_data==1)  
        {  
            pthread_cond_wait(&cond2,&mutex);  
        }  
        pthread_mutex_unlock(&mutex);  
    }while(strcmp(input,"#")!=0);  
    pthread_exit(NULL);  
}  
int main(int argc,char **argv)  
{  
    pthread_t id,id2;  
    pthread_cond_init(&cond,NULL);  
    pthread_cond_init(&cond2,NULL);  
    pthread_mutex_init(&mutex,NULL);  
    pthread_create(&id,NULL,(void *)read_buf,NULL);//返回值爲0,創建成功  
    pthread_create(&id2,NULL,(void *)write_buf,NULL);  
    pthread_join(id,NULL);  
    pthread_join(id2,NULL);  
    pthread_mutex_destroy(&mutex);  
    pthread_cond_destroy(&cond);  
    return 0;  
}  

運行結果:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章