linux線程同步 條件變數使用

來源:互聯網
上載者:User

à背景知識介紹

  1 互斥量

  互斥量函數有

      pthread_mutex_init 初始化一個互斥量

      pthread_mutex_lock 給一個互斥量加鎖

      pthread_mutex_trylock 加鎖,如果失敗不阻塞

      pthread_mutex_unlock 解鎖

互斥量從本質上說是一把鎖,在訪問共用資源前對互斥量進行加鎖,在訪問完成後釋放互斥量上的鎖。對互斥量進行加鎖以後,任何其他試圖再次對互斥量加鎖的線程將會被阻塞直到當前線程釋放該互斥鎖。

 2 條件變數

靜態方式使用PTHREAD_COND_INITIALIZER常量,如下:    
  pthread_cond_t   cond=PTHREAD_COND_INITIALIZER    
  動態方式調用pthread_cond_init()函數,API定義如下:    
  pthread_cond_init

pthread_cond_wait無條件等待
 ipthread_cond_timedwait   計時等待  

pthread_cond_signal()啟用一個等待該條件的線程,存在多個等待線程時按入隊順序啟用其中一個

而pthread_cond_broadcast()則啟用所有等待線程。 

條件變數實現的是一種通知機制,先線上程B中調用pthread_cond_wait(cond,mutex)等待條件變數被觸發而且在沒有被激發之前B就一直阻塞在pthread_cond_wait,一旦線上程A中調用pthread_cond_signal()從而激發條件變數,即通知線程B條件變數可用則B中中pthread_cond_wait由阻塞變成執行狀態(執行過程中mutex首先unlock->wait return->mutexlock )。

à互斥量和條件變數之間的關係

1 為了保證 線程A對條件變數可用的通知發出,線程B接收該通知的過程做到順序化。保證前一時刻有一個已經發出的條件變數可用通知之後,才讓B阻塞於pthread_cond_wait(為了實現這個,互斥量是個不錯的選擇)。

2如果沒有互斥量可能造成 thread_func訪問臨界資源時,main()也去訪問造成競爭。

à貼一個例子:

 

#include <pthread.h>#include <unistd.h>static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;struct node {int n_number;struct node *n_next;} *head = NULL;/*[thread_func]*/static void cleanup_handler(void *arg){    printf("Cleanup handler of second thread./n");    free(arg);    (void)pthread_mutex_unlock(&mtx);}static void *thread_func(void *arg){    struct node *p = NULL;    pthread_cleanup_push(cleanup_handler, p);    while (1) {    pthread_mutex_lock(&mtx);              while (head == NULL)   {               //這個while要特別說明一下,單個pthread_cond_wait功能很完善,為何這裡要有一個while (head == NULL)呢?因為pthread_cond_wait裡的線程可能會被意外喚醒,如果這個時候head != NULL,則不是我們想要的情況。這個時候,應該讓線程繼續進入pthread_cond_wait        pthread_cond_wait(&cond, &mtx);         // pthread_cond_wait會先解除之前的pthread_mutex_lock鎖定的mtx,然後阻塞在等待對列裡休眠,直到再次被喚醒(大多數情況下是等待的條件成立而被喚醒,喚醒後,該進程會先鎖定先pthread_mutex_lock(&mtx);,再讀取資源                                                //用這個流程是比較清楚的/*block-->unlock-->wait() return-->lock*/    }        p = head;        head = head->n_next;        printf("Got %d from front of queue/n", p->n_number);        free(p);        pthread_mutex_unlock(&mtx);             //臨界區資料操作完畢,釋放互斥鎖    }    pthread_cleanup_pop(0);    return 0;}int main(void){    pthread_t tid;    int i;    struct node *p;    pthread_create(&tid, NULL, thread_func, NULL);       /*[tx6-main]*/    for (i = 0; i < 10; i++) {        p = malloc(sizeof(struct node));        p->n_number = i;        pthread_mutex_lock(&mtx);             //需要操作head這個臨界資源,先加鎖,        p->n_next = head;        head = p;        pthread_cond_signal(&cond);        pthread_mutex_unlock(&mtx);           //解鎖        sleep(1);    }    printf("thread 1 wanna end the line.So cancel thread 2./n");    pthread_cancel(tid);             //關於pthread_cancel,有一點額外的說明,它是從外部終止子線程,子線程會在最近的取消點,退出線程,而在我們的代碼裡,最近的取消點肯定就是pthread_cond_wait()了。關於取消點的資訊,有興趣可以google,這裡不多說了    pthread_join(tid, NULL);    printf("All done -- exiting/n");    return 0;}

http://blog.csdn.net/hairetz/article/details/4535920

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.