条件变量
来源:互联网 发布:手机淘宝联系天猫客服 编辑:程序博客网 时间: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;}
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- 条件变量
- python列表中元素去重的几种方式
- 一个应用 可以有多个application
- PWN学习之[Toddler''s Bottle]-[passcode]
- 结构体大小
- 安卓系统启动过程
- 条件变量
- 用nginx的反向代理机制解决前端跨域问题
- 安卓 应用app启动过程
- nyoj267郁闷的c小加 中缀表达式转后缀求值
- 内存分哪些区 C++,ios,java
- gdb调试多进程多线程
- android 内存分哪些区
- Android Studio检测内存泄露和性能
- vue-按键修饰符