线程同步-条件变量

来源:互联网 发布:wordpress seo不好 编辑:程序博客网 时间:2024/05/02 01:06
条件变量用来等待不是用来上锁的,会自动阻塞一个线程,直到有触发条件,通常和互斥锁连用。
条件变量是利用线程间共享全局变量进行同步的一种机制,包含两步:一个线程等待条件变量的条件成立被阻塞,另一个线程使条件成立,并发出signal。
相关函数:
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);     
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);  
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);  //解除所有线程的阻塞
说明:
(1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER;属性置为NULL
      (2)等待条件成立.pthread_wait,pthread_timewait.wait()释放锁,并阻塞等待条件变量为真
      timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有一个线程wait)
      (3)激活条件变量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程)
      (4)清除条件变量:destroy;无线程等待,否则返回EBUSY

1. 初始化:
 条件变量采用的数据类型是pthread_cond_t, 在使用之前必须要进行初始化, 这包括两种方式:
静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要用pthread_cond_destroy对其进行清理.
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
成功则返回0, 出错则返回错误编号.
当pthread_cond_init的attr参数为NULL时, 会创建一个默认属性的条件变量; 非默认情况以后讨论.

2. 等待条件:
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);
成功则返回0, 出错则返回错误编号,这两个函数分别是阻塞等待和超时等待.
等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进行保护, 调用者把锁住的互斥量传递给函数. 函数把调用线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原子的. 这样便关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.
当pthread_cond_wait返回时, 互斥量再次被锁住.

3. 通知条件:
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
成功则返回0, 出错则返回错误编号.

这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再发送信号。

测试代码:

#include<string.h>#include<stdio.h>#include <pthread.h>pthread_cond_t qready = PTHREAD_COND_INITIALIZER;    //初始构造条件变量pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;    //初始互斥锁锁pthread_t tid1,tid2,tid3;int x = 10;int y = 20;//全局变量void *thrd_1(void *arg){        pthread_mutex_lock(&qlock);        while(x<y)        {            pthread_cond_wait(&qready,&qlock);//此处对线程1强制解锁执行线程2收到信号重新加锁        }        pthread_mutex_unlock(&qlock);        printf("1\n");        sleep(5);    }void *thrd_2(void *arg){        pthread_mutex_lock(&qlock);        x = 20;        y = 10;        printf("changedVALUE\n");        pthread_mutex_unlock(&qlock);        if(x > y)        {            pthread_cond_signal(&qready);        }        printf("2\n");    } void *thrd_3(void *arg){        pthread_join(tid1,NULL);//等待线程1结束        printf("3\n");    }int main(int argc,char **argv){        int err;        err = pthread_create(&tid1,NULL,thrd_1,NULL);        if(err != 0)        {            printf("error!");        }        err = pthread_create(&tid2,NULL,thrd_2,NULL);        if(err != 0)        {            printf("error!");        }        err = pthread_create(&tid3,NULL,thrd_3,NULL);        if(err != 0)        {           printf("error!");        }               pthread_join(tid2,NULL);//等待线程2结束        pthread_join(tid3,NULL);//等待线程3结束        return 0;          }

测试结果:

[root@libmaster zxd]# ./a.out 
changedVALUE
2
1
3



原创粉丝点击