c++11多线程记录6:条件变量(condition variables)
https://www.youtube.com/watch?v=13dFggo4t_I视频地址
实例1
考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deque中取出数据(读).
deque这个资源对象就需要用mutex做访问控制,代码如下:
std::deque<int> q;
std::mutex mu;
void func1() {
int ct = 10;
while (ct > 0) {
std::unique_lock<std::mutex> lock(mu);
q.push_front(ct);
lock.unlock();
std::this_thread::sleep_for(chrono::seconds(1));
ct --;
}
}
void func2() {
int data = 0;
while (data != 1 ) {
std::unique_lock<std::mutex> lock(mu);
if (!q.empty()) {
data = q.back();
q.pop_back();
lock.unlock();
...
} else {
lock.unlock();
}
}
}
int main() {
std::thread t1(func1);
std::thread t2(func2);
t1.join();
t2.join();
return 0;
}
线程t1中,循环向队列中推入数据,每次睡眠1秒;做为“生产者”.
线程t2中,不断地从队列中读出数据(先判断是否有数据);做为“消费者”.
存在一个问题:线程t2中,会先判断deque是否为空;如果为空,会执行unlock,然后马上进入下一次循环,造成busy waiting(反复频繁地判断某一状态是否为true).
一种解决方法如下:
void func2() {
...
} else {
lock.unlock();
std::this_thread::sleep_for(chrono::seconds(1));
}
}
在发现队列为空时睡眠一段时间time,可以一定程度上解决问题。
但是变量time设置成什么数值并不好确定;设置的过小,可能会回到busy waiting;设置的过大,会导致不能及时的获取数据
Condition variable
用条件变量可以很好的处理这个问题,让消费者不用“盲目等待”
std::deque<int> q;
std::mutex mu;
std::condition_variable cond;
void func1() {
int ct = 10;
while (ct > 0) {
std::unique_lock<std::mutex> lock(mu);
q.push_front(ct);
lock.unlock();
cond.notify_one(); // wake up one waiting thread
// cond.notify_all(); // wake up all waiting threads
std::this_thread::sleep_for(chrono::seconds(1));
ct --;
}
}
void func2() {
int data = 0;
while (data != 1 ) {
std::unique_lock<std::mutex> lock(mu);
cond.wait(lock, [](){ return !q.empty(); });
data = q.back();
q.pop_back();
lock.unlock();
}
}
生产者线程中,数据被推入deque后执行notify_one(),就可以唤醒某一个线程;类似于银行柜台叫号.
消费者线程中,只需要cond.wait(lock,...),睡眠等待,直到被“叫号”;睡眠等待过程中不占用cpu时间.(被唤醒时,第二个参数如果返回false会继续睡眠,为true则会往下执行)
注意这里cond.wait(lock)进入睡眠之前会先释放对lock的占用;被唤醒时会先占用mutex.
小结
condition_variable粗略的说,可能类似一个“唤醒服务”.
c++11多线程记录6:条件变量(condition variables)的更多相关文章
- [development][C] 条件变量(condition variables)的应用场景是什么
产生这个问题的起因是这样的: [:] <tong> lilydjwg: 主线程要启动N个子线程, 一个局部变量作为把同样的参数传入每一个子线程. 子线程在开始的十行会处理完参数. ...
- 深入解析条件变量(condition variables)
深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization m ...
- python线程条件变量Condition(31)
对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition. 一.线程条件变 ...
- 多线程编程中条件变量和的spurious wakeup 虚假唤醒
1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1) 线程等待 ...
- python多线程编程5: 条件变量同步-乾颐堂
互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还 ...
- 练习生产者与消费者-PYTHON多线程中的条件变量同步-Queue
以前练习过,但好久不用,手生,概念也生了, 重温一下.. URL: http://www.cnblogs.com/holbrook/tag/%E5%A4%9A%E7%BA%BF%E7%A8%8B/ ~ ...
- [转] 条件变量(Condition Variable)详解
http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A ...
- linux C++ 多线程使用pthread_cond 条件变量
1. 背景 多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的互斥操作. 但是互斥锁有一个明显到缺点: 只有两种状态,锁定和非锁定. 而条件变量则通过允许线程阻塞并等待另一 ...
- java多线程技术之条件变量
上一篇讲述了并发包下的Lock,Lock可以更好的解决线程同步问题,使之更面向对象,并且ReadWriteLock在处理同步时更强大,那么同样,线程间仅仅互斥是不够的,还需要通信,本篇的内容是基于上篇 ...
随机推荐
- PAT刷题 (Java语言)
1001. A+B Format (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Calculate ...
- JVM相关内容简介(转)
JAVA堆内存管理是影响性能主要因素之一.堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的. 先看下JAVA堆内存是如何划分的,如图: JVM内存划分为 ...
- python 路径拼接
>>> import os>>> os.path.join('/hello/','good/boy/','doiido')>>>'/hello/g ...
- MYSQL避免重复插入记录的三种方法
方案一:使用ignore关键字 如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用: insert ignore into table_name(ema ...
- Fluent Meshing生成空心球体网格(空心部分不生成网格)
原视频下载地址: https://pan.baidu.com/s/1OJdHuIJd7pAr7cHgVCD_0g 密码: puiq
- 聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里)
redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的.B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试) 还有个几个姊妹篇:介绍 ...
- Debian 9安装java与设置环境变量
安装默认JRE / JDK 先更新软件包索引: apt update 检查是否已安装Java: java -version 如果当前未安装Java,您将看到以下输出: Output-bash: jav ...
- python MySQLdb 字典(dict)结构数据插入mysql
背景: 有时候直接操作数据库字段比较多,一个个写比较麻烦,而且如果字段名跟数据库一致,那生成为字典后,是否能直接使用字典写入数据库呢,这样会方便很多,这里简单介绍一种方法. 实例: 1. 假设数据库表 ...
- nginx https 转发
add_header Content-Security-Policy upgrade-insecure-requests;
- Redis 服务监控 redis-faina 命令查看 和 redis-live 界面查看
Redis现在在很多公司中应用已经很广泛了,但是如何监控redis,实时的观察redis的性能,下面就关于Redis的常用监控介绍一下. 一.使用redis自带的info命令和monitor命令现在常 ...