POSIX多線程中的pthread_cond_wait() 函數 使用示例2個

 由於工作站軟件的移植牽涉到這方面的內容, 搜一最近一直在學習Linux線程方面的知識!由於<Beginning  the Linux programming>這本書上沒有將條件變量的問題,所以不能理解的一個函數就是pthread_cond_wait().
    今天終於有點明白了,趕快記下心得!
    條件變量的結構爲pthread_cond_t,函數pthread_cond_init()被用來初始化一個條件變量。它的原型爲:

  extern int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));

  其中cond是一個指向結構pthread_cond_t的指針,cond_attr是一個指向結構pthread_condattr_t的指針。結構 pthread_condattr_t是條件變量的屬性結構,和互斥鎖一樣我們可以用它來設置條件變量是進程內可用還是進程間可用,默認值是 PTHREAD_ PROCESS_PRIVATE,即此條件變量被同一進程內的各個線程使用。注意初始化條件變量只有未被使用時才能重新初始化或被釋放。釋放一個條件變量的函數爲pthread_cond_destroy(pthread_cond_t cond)。 

    也可以靜態的初始化條件變量

     pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;

  函數pthread_cond_wait()使線程阻塞在一個條件變量上。它的函數原型爲:

  extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));

   調用這個函數時,線程解開mutex指向的鎖並被條件變量cond阻塞。線程可以被函數pthread_cond_signal和函數 pthread_cond_broadcast喚醒線程被喚醒後,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這裏,被等待被下一次喚醒。這個過程一般用while語句實現。

    通過下面的程序來理解:

__________________華麗的CODE分割線_________________________

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  //初始化條件變量

void *thread1(void *);
void *thread2(void *);

int i=1;
int main(void)
{
        pthread_t t_a;
        pthread_t t_b;
        pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創建進程t_a*/
        pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創建進程t_b*/
        pthread_join(t_b, NULL);/*等待進程t_b結束*/
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
         exit(0);
}

void *thread1(void *junk)
{
        for(i=1;i<=9;i++)
        {
             pthread_mutex_lock(&mutex);//
             if(i%3==0)
                 pthread_cond_signal(&cond);/*條件改變,發送信號,通知t_b進程*/
              else      
                  printf("thead1:%d/n",i);
              pthread_mutex_unlock(&mutex);//*解鎖互斥量*/
              printf("Up Unlock Mutex/n");     
              sleep(1);
        }

}

void *thread2(void *junk)
{
        while(i<9)
        {
              pthread_mutex_lock(&mutex);

            if(i%3!=0)
                   pthread_cond_wait(&cond,&mutex);/*等待*/
            printf("thread2:%d/n",i);
            pthread_mutex_unlock(&mutex);
            printf("Down Ulock Mutex/n");

            sleep(1);
                }

}

___________________至關重要的絢爛的結果分割線_________________

thead1:1
Up Unlock Mutex
thead1:2
Up Unlock Mutex
Up Unlock Mutex
thread2:3
Down Ulock Mutex
thead1:4
Up Unlock Mutex
thead1:5
Up Unlock Mutex
Up Unlock Mutex
thread2:6
Down Ulock Mutex
thead1:7
Up Unlock Mutex
thead1:8
Up Unlock Mutex
Up Unlock Mutex
thread2:9
Down Ulock Mutex

_________________HOW IT WORKS________

i不是三的倍數的時候.

thread2條件變量阻塞,釋放Mutex

thread1加鎖,打印thread1:i,釋放鎖,打印"Up Unlock Mutex"

i爲3的倍數的時候,

thread1,加鎖,條件變量通知,喚醒條件變量阻塞線程,打印"Up Unlock Mutex"

thread2,被喚醒,加鎖,打印"thread2:i",釋放鎖,打印"Down Ulock Mutex"

 

    所以說函數pthread_cond_wait()調用時,不僅對條件變量起作用,還對互斥鎖有作用!

 

++++++++++++++++唯美的好書推薦線++++++++++++

"Beiginning Linux Programming" by Neil Matthrew & Richard Stones

You can choose the English version or Chinese version, but I recommend the English one. Maybe it' easier to understand what the authers say than the Chinese one ,  even if you're Chinese.

 

 

--------------------------------------分割線----------------------------------------------------

以下示例集中演示了互斥鎖和條件變量的結合使用,以及取消對於條件等待動作的影響。在例子中,有兩個線程被啓動,並等待同一個條件變量,如果不使用退出回調函數(見範例中的註釋部分),則tid2將在pthread_mutex_lock()處永久等待。如果使用回調函數,則tid2的條件等待及主線程的條件激發都能正常工作。

#include   <stdio.h>
#include   <pthread.h>
#include   <unistd.h>

pthread_mutex_t   mutex;
pthread_cond_t     cond;

void   *   child1(void   *arg)
{
                pthread_cleanup_push(pthread_mutex_unlock,&mutex);     /*   comment   1   */
                while(1){
                                printf( "thread   1   get   running   /n ");
                printf( "thread   1   pthread_mutex_lock   returns   %d/n ",
pthread_mutex_lock(&mutex));
                pthread_cond_wait(&cond,&mutex);
                                        printf( "thread   1   condition   applied/n ");
                pthread_mutex_unlock(&mutex);
                                        sleep(5);
        }
                pthread_cleanup_pop(0);           /*   comment   2   */
}

void   *child2(void   *arg)
{
                while(1){
                                sleep(3);                               /*   comment   3   */
                                printf( "thread   2   get   running./n ");
                printf( "thread   2   pthread_mutex_lock   returns   %d/n ",
pthread_mutex_lock(&mutex));
                pthread_cond_wait(&cond,&mutex);
                printf( "thread   2   condition   applied/n ");
                pthread_mutex_unlock(&mutex);
                sleep(1);
                }
}

int   main(void)
{
                int   tid1,tid2;

                printf( "hello,   condition   variable   test/n ");
                pthread_mutex_init(&mutex,NULL);
                pthread_cond_init(&cond,NULL);
                pthread_create(&tid1,NULL,child1,NULL);
                pthread_create(&tid2,NULL,child2,NULL);
                do{
                sleep(2);                                       /*   comment   4   */
                                pthread_cancel(tid1);               /*   comment   5   */
                                sleep(2);                                       /*   comment   6   */
                pthread_cond_signal(&cond);
        }while(1);    
                sleep(100);
                pthread_exit(0);
}  


如果不做註釋5的pthread_cancel()動作,即使沒有那些sleep()延時操作,child1和child2都能正常工作。註釋3和註釋4的延遲使得child1有時間完成取消動作,從而使child2能在child1退出之後進入請求鎖操作。如果沒有註釋1和註釋2的回調函數定義,系統將掛起在child2請求鎖的地方;而如果同時也不做註釋3和註釋4的延時,child2能在child1完成取消動作以前得到控制,從而順利執行申請鎖的操作,但卻可能掛起在pthread_cond_wait()中,因爲其中也有申請mutex的操作。child1函數給出的是標準的條件變量的使用方式:回調函數保護,等待條件前鎖定,pthread_cond_wait()返回後解鎖。

條件變量機制不是異步信號安全的,也就是說,在信號處理函數中調用pthread_cond_signal()或者pthread_cond_broadcast()很可能引起死鎖

發佈了30 篇原創文章 · 獲贊 21 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章