Linux线程同步——条件变量
互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的。
条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。
通常条件变量和互斥锁同时使用。
和条件变量使用有关的几个重要函数:
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. 初始化:
条件变量采用的数据类型是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, 出错则返回错误编号.
这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再给线程发送信号.
条件变量使用示例
下面是个非常简单的例子,很好的演示了条件变量如何使用。
我将创建一个生产者线程,两个消费者线程,通过互斥量和条件变量同步他们的生产和消费操作。
需要注意的一个地方是,pthread_cond_wait操作必须传入一个条件变量和互斥量,线程先对互斥量上锁,然后再执行pthread_cond_wait,pthread_cond_wait会将互斥量解锁。
pthread_cond_wait在while循环中而不在if中的原因是,“可能被意外唤醒”,所以需要在唤醒之后再检查缓冲区。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> pthread_cond_t condc,condp;
pthread_mutex_t the_mutex; unsigned int buffer = ;
const int MAX = ; void *producer(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer != ) pthread_cond_wait(&condp, &the_mutex);
sleep();
buffer = i;
printf("producer pthread produce one production %d.\n", i);
pthread_cond_broadcast(&condc);//唤醒两个消费者线程
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
} void *consumer1(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
printf("consumer1 pthread consume one production %d.\n", buffer);
buffer = ;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
}
void *consumer2(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
printf("consumer2 pthread consume one production %d.\n", buffer);
buffer = ;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
} int main(void){
pthread_t pro, con1, con2;
pthread_mutex_init(&the_mutex,);
pthread_cond_init(&condc,);
pthread_cond_init(&condp,);
pthread_create(&con1, , consumer1, );
pthread_create(&pro, , producer, );
pthread_create(&con2, , consumer2, );
pthread_join(pro, );
pthread_join(con1, );
pthread_join(con2, );
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
pthread_mutex_destroy(&the_mutex);
return ;
}
运行结果
Linux线程同步——条件变量的更多相关文章
- linux Posix线程同步(条件变量) 实例
条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行 应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信 ...
- pThreads线程(三) 线程同步--条件变量
条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...
- linux线程同步(2)-条件变量
一.概述 上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...
- 【转】 Linux 线程同步的三种方法
线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...
- Java线程:条件变量、原子量、线程池等
一.条件变量 条件变量实现了java.util.concurrent.locks.Condition接口,条件变量的实例化就是通过一个Lock对象上调用newCondition()方法获得的,这样条件 ...
- linux 线程同步(二)
信号量 信号量是相互排斥锁的升级版把相互排斥锁中1变成了n.举个简单的样例:如果如今有10个人,有一部手机.这10个人都竞争来使用手机打电话这就是相互排斥锁.对于信号量,如今可能是有4部手机,这10个 ...
- Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
- Linux 线程同步的三种方法(互斥锁、条件变量、信号量)
互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...
- linux多线程-互斥&条件变量与同步
多线程代码问题描述 我们都知道,进程是操作系统对运行程序资源分配的基本单位,而线程是程序逻辑,调用的基本单位.在多线程的程序中,多个线程共享临界区资源,那么就会有问题: 比如 #include < ...
随机推荐
- HTTP协议、HTTP协议原理分析
百度百科中说明: 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为 ...
- dataframe.isnull()函数, DatetimeIndex,黄包车代码155行
待解决 feature 4 完全没懂 feature 5 219行: if (row.userid == action['userid'][row.max_index - 1]): ????
- 如何实现session跨服务器共享
Session共享有多种解决方法,常用的有四种:客户端Cookie保存.服务器间Session同步.使用集群管理Session.把Session持久化到数据库. 1.客户端Cookie保存 以cook ...
- Elasticsearch地理位置总结
更多内容请参考 : https://www.felayman.com 翻译版本:https://es.xiaoleilu.com/310_Geopoints/00_Intro.html 官方原文:ht ...
- HTML 5 使用 FileReader、FormData实现文件上传
一.FileReader FileReader 对象允许Web应用程序异步读取存储在用户计算机中的文件(或缓冲区的原始数据),使用File或Blob对象指定要读取的文件或数据. 1.1 实例化 var ...
- MySQL实例crash的案例分析
[作者] 王栋:携程技术保障中心数据库专家,对数据库疑难问题的排查和数据库自动化智能化运维工具的开发有强烈的兴趣. [问题描述] 我们生产环境有一组集群的多台MySQL服务器(MySQL 5.6.21 ...
- protobuffer php使用
protobuffer是google推出的一种数据传的方式,具体压缩,体积小的特点 protobuffer本身不支持php,若要把.proto文件转化为php支持的文件,需要使用第三方的程序 alle ...
- 杭电OJ第11页2010-2019道题(C语言)
2010. 水仙花数 问题描述 Problem Description 春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的: "水仙花数"是指一个三位 ...
- Swift 学习指引
以下指引是基于最新的 Swift 4.0 为基础为而言. 如你在参考3.0以下版本, 那你就不要说你会 Swift, 3.0 之前是 Objective-C 的搬迁(80%),是不成熟的语言, 看着很 ...
- Vue的实时时间转换Demo
Vue的实时时间转换Demo time.html: <!DOCTYPE html> <html lang="en"> <head> <me ...