linux筆記之條件變量

一.概念:

  • 同步:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源。
  • 通俗來講,互斥只是實現了安全問題,而有的時候,它並不高效,所以在此引出了條件變量,它可以用來實現高效。
  • 互斥鎖和條件變量分別用來實現互斥和同步,是一對黃金搭檔。

二.涉及的函數

  • 創建一個條件變量有兩種方式

    • 定義一個全局變量如下:

      pthread_cond_t  cond=PTHREAD_COND_INITIALIZER;
    • 使用初始化函數:
      這裏寫圖片描述

  • 條件變量的銷燬函數
    這裏寫圖片描述

  • 條件變量等待函數
    這裏寫圖片描述
    條件變量有兩個等待函數。二者的區別就在於pthread_cond_timedwait()比pthread_cond_wait()函數多了一個參數abstime,此參數可以設定等待超時,如果達到abstime所指定的時刻,仍然沒有別的線程來喚醒當前線程,就返回ETIMEDOUT。
    pthread_cond_wait在阻塞式等待,這個函數做了以下三步操作:
    1.釋放Muxtex
    2.阻塞等待
    3.當被喚醒時,重新獲得Mutex並返回
  • 條件變量喚醒函數
    這裏寫圖片描述
    有兩個喚醒函數,區別是:
    pthread_cond_signal喚醒的是某個Condition Variable上等待的另一個線程,也可以調用
    pthread_cond_broadcast喚醒在這個Condition Variadle上等待的所有線程
    ##三.代碼演示:
    下列程序演示了一個生產者-消費者的例子,表現同步互斥的效果
  • 以下代碼是隻加了互斥鎖的代碼,在消費者線程中加入了sleep(100);以達到增強生產者線程的競爭力的效果;代碼以及效果圖如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<pthread.h>
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
typedef struct _node
{
    struct _node*  _next;
    int data;
}_node,*_node_p,**_node_pp;

_node_p alloc(int data)
{
    _node_p _node=(_node_p)malloc(sizeof(data));
    if(_node==NULL)
    {
        perror("malloc");
        exit (0);
    }
    _node->data=data;
    _node->_next=NULL;
    return _node;
}
void delete_node(_node_p temp)
{
    if(!temp)
    free(temp);
}
static int is_empty(_node_p _h)
{
    if(NULL==_h->_next)
    {
        return 1;
    }
    return 0;
}
void show_List(_node_p _h)
{
    assert(_h);
    _node_p temp=_h->_next;
    while(NULL!=temp)
    {
        printf("%d ",temp->data);
        temp=temp->_next;
    }
    printf("\n");
}


void pop_List(_node_p _h,int* _o)
{
    if(!is_empty(_h))
    {
        _node_p temp=_h->_next;
        _h->_next=temp->_next;
        *_o=temp->data;
        delete_node(temp);
    }
}

void init_List(_node_pp _h)
{
    *_h=alloc(0);
}
void destory_List(_node_p _h)
{
    int data;
    while(is_empty(_h));
    {
        pop_List(_h,&data);
    }
    delete_node(_h);
}
void push_List(_node_p _h,int data)
{
    _node_p Newnode=alloc(data);
    Newnode->_next=_h->_next;   
    _h->_next=Newnode;
}
static void* consumer(void* _h)
{
    _node_p head=(_node_p) _h;
    for(;;)
    {
        pthread_mutex_lock(&lock);
        int data=rand()%1000;
        pop_List(head,&data);
        pthread_mutex_unlock(&lock);
        printf("consumer:%d\n",data);
        sleep(100);
    }
}
static void* producter(void* _h)
{
    _node_p head=(_node_p) _h; 
    for(;;)
    {
        pthread_mutex_lock(&lock);
        int i=rand()%1000;
        push_List(head,i);
        pthread_mutex_unlock(&lock);
        printf("producter:%d\n",i);
        sleep(1);
    }
}
int main()
{
    _node_p head=NULL;
    init_List(&head);
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL,*consumer,head);
    pthread_create(&tid2,NULL,*producter,head);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_cond_destroy(&cond);
    return 0;
}

結果圖如下:
這裏寫圖片描述
出現了只生產不消費的情況。
要解決如上問題:則需要時生產者和消費者同步起來:使用條件變量.

  • 使用條件變量解決上述問題:
    代碼如下:
static void* consumer(void* _h)
{
    _node_p head=(_node_p) _h;
    for(;;)
    {
        pthread_mutex_lock(&lock);
        int data=rand()%1000;
        while(is_empty(head))
        {
            pthread_cond_wait(&cond,&lock);
        }
        pop_List(head,&data);
        pthread_mutex_unlock(&lock);
        printf("consumer:%d\n",data);
        sleep(100);
    }
}
static void* producter(void* _h)
{
    _node_p head=(_node_p) _h; 
    for(;;)
    {
        pthread_mutex_lock(&lock);
        int i=rand()%1000;
        push_List(head,i);
        pthread_mutex_unlock(&lock);
        printf("producter:%d\n",i);
        pthread_cond_signal(&cond);
        sleep(1);
    }
}

結果圖:這裏寫圖片描述

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