条件变量

来源:互联网 发布:手机淘宝联系天猫客服 编辑:程序博客网 时间:2024/05/15 00:00

一、条件变量初始化

POSIX条件变量由一个pthread_cond_t型的变量表示。使用条件变量前需要对它进行初始化,所用的接口函数原型如下:
int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);
    cond参数指向要初始化的条件变量,attr参数指向描述条件变量属性的结构体。attr可以为NULL,表示使用默认属性。

二、等待

当程序中需要等待一个条件变量时,可以用下面的函数:
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,  const struct timespec *abstime);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

这些函数都有一个指向互斥量的参数mutex,说明条件变量必须与互斥量搭配使用。    调用这些函数时,首先,指定的互斥量将被释放,然后线程将阻塞,等待条件变量的触发。函数返回前,互斥量重新被线程获取。
pthread_cond_timedwait与pthread_cond_wait的区别在于,前者有一个由abstime指定的超时时间限制,当线程阻塞的时间超过了这个时间就会自动醒来。

三、触发

触发一个条件变量可以用以下函数:
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);

pthread_cond_signal可以唤醒一个或多个正在等待cond参数所指向的条件变量的线程,而pthread_cond_broadcast则可以唤醒全部正在等待cond参数所指向的条件变量的线程。
 
注意:POSIX标准只规定pthread_cond_signal函数唤醒至少一个睡眠中的线程,并没有规定只唤醒一个。

四、销毁

条件变量不用之后,应该用下面的函数进行销毁:
int pthread_cond_destroy(pthread_cond_t *cond);
 

五、条件变量的应用

#include <stdio.h>#include <pthread.h>#include <time.h>#include <string.h>// 互斥锁pthread_mutex_t mutex;// 条件变量pthread_cond_t cond;// 共享资源int num = 0;// 生产者线程工作函数void *Produce(void *v){while (1){int time = rand() % 100 + 1;usleep(time*10000);pthread_mutex_lock(&mutex);    // 抢锁printf ("生产资源\n");num += 2;// 唤醒所有在条件变量 cond 上进行等待的线程pthread_cond_broadcast(&cond);pthread_mutex_unlock(&mutex);  // 解锁}}// 消费者线程工作函数void *Consum(void *v){while (1){int time = rand() % 100 + 1;usleep(time*10000);pthread_mutex_lock(&mutex);    // 抢锁/*if (num == 0){printf ("没有资源\n");pthread_mutex_unlock(&mutex);  // 解锁continue;}*/while (num == 0){// 陷入沉睡, 等待某个人条件变量满足// 第一个参数是等待哪个条件变量,第二个参数是相关的互斥锁// 一旦 进行 条件等待,会陷入沉睡,让出CPU资源,阻塞在当前位置// 工作步骤:// 1、解锁互斥锁,让其他线程可以抢夺这个锁// 2、当被唤醒的时候,和所有在互斥锁上阻塞的线程一起抢夺锁,抢到就继续执行,抢不到 继续抢// 外层需要有一个循环,判断当前条件是否满足,因为就算该线程被唤醒,num 也不一定就是一个大于 0 的数pthread_cond_wait(&cond, &mutex);}num--;printf ("消费一个消息, 剩余资源: %d\n", num);pthread_mutex_unlock(&mutex);  // 解锁}}int main(){srand ((unsigned int)time(NULL));// 初始化互斥锁pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_t produceId;pthread_t consumId;// 创建生产者线程pthread_create(&produceId, NULL, Produce, NULL);int i = 0;for (i = 0; i < 3; i++){// 创建消费者线程pthread_create(&consumId, NULL, Consum, NULL);pthread_detach(consumId);}pthread_join(produceId, NULL);// 销毁互斥锁pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;}


原创粉丝点击