POSIX多线程中的pthread_cond_wait() 函数 使用示例2个

来源:互联网 发布:淘宝客流量是什么意思 编辑:程序博客网 时间:2024/05/16 08:41

 由于工作站软件的移植牵涉到这方面的内容, 搜一最近一直在学习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()很可能引起死锁