四十一、Linux 线程——线程同步之条件变量
41.1 概念
41.1.1 条件变量的介绍
- 互斥锁的缺点是它只有两种状态:锁定和非锁定
- 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足
- 条件变量内部是一个等待队列,放置等待的线程,线程在条件变量上等待和通知,互斥锁用来保护等待队列(对等待队列上锁),条件变量通常和互斥锁一起使用
- 条件变量允许线程等待特定条件发生,当条件不满足时,线程通常先进入阻塞状态,等待条件发生变化。一旦其它的某个线程改变了条件,可唤醒一个或多个阻塞的线程
- 具体的判断条件还需用户给出
- 条件变量数据类型: pthread_cond_t
41.1.2 条件变量创建和销毁
#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);
- 函数参数:
- cond:条件变量
- attr:条件变量属性
- 返回值:
- 成功,返回 0;出错,返回错误编号
41.1.3 条件变量等待操作
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timewait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout); struct timespec {
time_t tv_sec; /** seconds */
ong tv_nsec; /** nanoseconds */
};
- 函数参数:
- cond:条件变量
- mutex:互斥锁
- 返回值:成功,返回 0,出错,返回错误编号
- 互斥锁 mutex 是对条件变量 cond 的保护
- 线程由于调用 wait 函数阻塞,否则释放互斥锁
41.1.4 条件变量通知操作
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
- 函数参数:
- cond:条件变量
- 返回值:成功,返回 0;失败,返回错误编号
- 当条件满足,线程需要通知等待的线程
- pthread_cond_signal 函数通知单个线程
- pthread_cond_broadcast 函数通知所有线程
41.1.5 pthread_cond_wait(cond, mutex) 函数内部流程
- unlock(&mutex):释放锁
- lock(&mutex)
- 将线程自己插入到条件变量的等待队列中
- unlock(&mutex);
- 当前等待的线程阻塞 <<== 等待其他线程通知唤醒(signal 或 broadcast)
- 在唤醒后,lock(&mutex)
- 从等待队列中删除线程自己
41.2 例子
一个线程负责计算结果,一个线程负责获取结果
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> /** 两个线程定义的共享资源 */
typedef struct {
int res;
int is_wait; ///< 用户给出的用于判断的条件
pthread_cond_t cond; ///< 条件变量
pthread_mutex_t mutex; ///< 互斥锁
}Result; /** 计算并将结果放置在 Result 中的线程运行函数 */
void *set_fn(void *arg)
{
Result *r = (Result *)arg;
int i = ;
int sum = ; for(; i <= ; i++){
sum += i;
} /** 将结果放置到 Result 中 */
r->res = sum; pthread_mutex_lock(&r->mutex);
/** 判断获取结果的线程是否准备好 */
while(!r->is_wait){
pthread_mutex_unlock(&r->mutex);
usleep();
pthread_mutex_lock(&r->mutex);
}
pthread_mutex_unlock(&r->mutex); /** 通知唤醒等待的那个获取结果的线程 */
pthread_cond_broadcast(&r->cond); return (void *);
} /** 获得结果的线程运行函数 */
void *get_fn(void *arg)
{
Result *r = (Result *)arg; /** 对两个线程共享的判断条件进行保护(加锁) */
/** 两个线程对判断条件的操作是互斥的 */
pthread_mutex_lock(&r->mutex);
/** 当线程启动后,将此变量设置为1,代表此线程已经准备好了 */
r->is_wait = ; /** 获取结果的线程等待 */
pthread_cond_wait(&r->cond, &r->mutex); /** 被唤醒后 */
pthread_mutex_unlock(&r->mutex); /** 去获取计算结果 */
int res = r->res;
printf("0x%lx get sum is %d\n", pthread_self(), res); return (void *);
} int main(void)
{
int err;
pthread_t cal, get; Result r;
r.is_wait = ;
pthread_cond_init(&r.cond, NULL);
pthread_mutex_init(&r.mutex, NULL); /** 启动获取结果的线程 */
if((err = pthread_create(&get, NULL, get_fn, (void *)&r)) != ){
perror("pthread create error");
} /** 启动计算结果的线程 */
if((err = pthread_create(&cal, NULL, set_fn, (void *)&r)) != ){
perror("pthread create error");
} pthread_join(cal, NULL);
pthread_join(get, NULL); pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex); pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex);
return ;
}
编译执行结果:
四十一、Linux 线程——线程同步之条件变量的更多相关文章
- Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
- linux线程同步(2)-条件变量
一.概述 上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...
- 线程同步,条件变量pthread_cond_wait
与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享的全局变量进行同步的一种机制,主 ...
- C++11 中的线程、锁和条件变量
转自:http://blog.jobbole.com/44409/ 线程 类std::thread代表一个可执行线程,使用时必须包含头文件<thread>.std::thread可以和普通 ...
- 【转】【C++】C++ 中的线程、锁和条件变量
线程 类std::thread代表一个可执行线程,使用时必须包含头文件<thread>.std::thread可以和普通函数,匿名函数和仿函数(一个实现了operator()函数的类)一同 ...
- (转)Java线程:新特征-条件变量
Java线程:新特征-条件变量 条件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量.但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往 ...
- Linux多线程编程详细解析----条件变量 pthread_cond_t
Linux操作系统下的多线程编程详细解析----条件变量 1.初始化条件变量pthread_cond_init #include <pthread.h> int pthread_cond_ ...
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...
- linux C++ 多线程使用pthread_cond 条件变量
1. 背景 多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的互斥操作. 但是互斥锁有一个明显到缺点: 只有两种状态,锁定和非锁定. 而条件变量则通过允许线程阻塞并等待另一 ...
随机推荐
- [CQOI2017]老C的方块
题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=4823 题解 观察那四种条件 有没有什么特点? 我们可以把蓝线两边的部分看做两个区域,这样 ...
- MySQL课堂小测
目录 一.基本知识与操作方法 二.小测具体内容 (一)向数据库表中添加记录 (二)下载并导入world.sql (三)数据库查询与输出 (四)查询数据库并求某字段和 (五)查询数据库并取最大& ...
- Jupyter ~ 像写文章般的 Coding (附:同一个ipynb文件,执行多语言代码)
前面用了好久Notebook来交互式编程了,这次说说几个其他的选项: Notebook Markdown 这次选Markdown模式(关于Markdown基础可以看之前写的Markdown Base) ...
- Python数据结构之栈的实现
一图胜千言,看图! 代码code: #coding:utf-8 #常见数据结构之栈的实现 class Stack(): #创建Stack类 def __init__(st,size): st.stac ...
- 什么是Zookeeper?
https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665514106&idx=1&sn=e54aae8cf68f5a ...
- ES6学习:Map结构的目的和基本用法
Map结构的目的和基本用法 JavaScript的对象(Object)本质上是键值对的集合(Hash结构),但是只能用字符串作为键.这给它的使用带来了很大的限制. 1 2 3 4 5 6 7 8 ...
- Http如何利用304让浏览器去更新数据
ETag 是 Entity Tag 的缩写,中文译过来就是实体标签的意思.在HTTP1.1协议中其实就是请求HEAD中的一个属性而已. HTTP/1.1 200 OK Date: Mon, 23 Ma ...
- 简洁架构的思想,基于go实现
https://manuel.kiessling.net/2012/09/28/applying-the-clean-architecture-to-go-applications/ 从 Clean- ...
- 2017-12-14python全栈9期第一天第四节之python分类
python的环境. 编译型:一次性将所有程序编译成二进制文件. 缺点:开发效率低,不能跨平台. 优点:运行速度快. :C,C++等等. 解释型:当程序执行时,一行一行的解释. 优点:开发效率高,可以 ...
- flask 渲染jinja2模版和传参
渲染模版(html文件) A.模版文件(html)放入到template目录下,项目启动的时候会从template目录里查找, B.从flask中导入“render_tempalte”函数 C.在视图 ...