boost库(条件变量)
1相关理念
(1)类名
条件变量和互斥变量都是boost库中被封装的类。
(2)条件变量
条件变量是thread库提供的一种等待线程同步的机制,可实现线程间的通信,它必须与互斥量配合使用,等待另一个线程中某个事件发生后本线程才能继续执行。
(3)互斥变量
互斥量是一种用于多线程编程的手段,它可以在多线程编程中防止多个线程同时操作共享资源[或称为临界区 ]。思想为:在每个线程开始的第一条语句使用获取互斥变量“锁有权”的语句,一旦一个线程[线程1]锁住了互斥量,那么其它线程只有等待线程1解锁互斥量后且另一线程[线程2]又获取到互斥变量的“锁有权”后才能运行这个线程[线程2]后面的代码。
(4)互斥量有可能的缺点
[1]互斥变量的使用让线程整个整个的运行。
[2]如果“同时”创建多线程,则首先获取到互斥变量“锁有权”的线程是不定的。
(5)条件变量的简单应用场景
有时候我们需要先运行某个线程一会儿后才能运行另一个线程,或者是需要先运行某个线程[线程1]一会儿后必须运行另一个线程[线程2]后线程1才能够继续运行。C++ boost库对条件变量的封装 就是来解决这些问题的。
2 条件变量的使用机制总结
C++boost 的thread库提供两种条件变量对象condition_variable及condition_variable_any,由于后者能够适用于更广泛的互斥量类型,所以一般用condition_variable_any,其类摘要如下:
- class condition_variable_any
- {
- public:
- void notify_one();
- void notify_all();
- template <typename lock_type>
- void wait(lock_type &lock);
- template<typename lock_type, typename predicate_type>
- void wait(lock_type &lock,predicate_type predicate);
- template<typename lock_type, typename duration_type>
- bool timed_wait(lock_type &lock, duration_type const& rel_time);
- }
条件变量condition_variable_any中只封装了]notify_one(),notify_all()和wait()系列两类函数。
2.1参考书对条件变量的描述
拥有条件变量的线程先锁定互斥量,然后循环检查某个条件,如果条件不满足,那么就调用成员函数wait()等至条件满足。而其它线程处理条件变量要求的条件,当条件满足时调用它的成员函数notify_one()或notify_all(),以通知所有正在等待条件变量的线程停止等待继续执行。
其实这一小段话就将condition_variable_any类摘要的使用机制给描述了,但是不得不承认我并没有读懂,所以还得继续写程序验证一下条件变量到底封装了怎么一个机制。
2.2实践总结笔记
(1)简单使用条件变量步骤
[1]定义生存期和作用域能够应用于多线程中的条件变量对象和互斥变量对象。条件变量对象的个数据程序需求制定。
condition_variable_any con_var_1; condition variable_anu con_var_2; mutex mu; |
[2]每个线程对应函数的第一条语句使用锁定互斥量的语句,最后一条语句使用解锁互斥量的语句。【如果不使用条件变量来实现线程通信,则如此就能够使多线程中单个线程一个接连一个的运行,运行时间和场合的不同,各线程运行的顺序也不同】
void thread_fun_1() { mu.lock(); …… mu.unlock(); } |
void thread_fun_2() { mu.lock(); …… mu.unlock(); } |
[3]thread_fun_1()输出”123456789”字符串的奇数数字,thread_fun_2()输出字符串的偶数数字,并且用条件变量和多线程来实现。
void thread_fun_1( const string &str ) |
void thread_fun_2( const string &str ) |
其中i可以是两个线程函数都能够访问的全局变量。
[4]在主程序中创建两个线程来跑这两个线程函数。
thread th_1(thread_fun_1, “123456789”); thread th_2(thread_fun_2, ”123456789”); |
可以使用getchar()函数让运行窗口停留,程序运行效果为目标期待的样子【前提是知道boost库的使用需要包含的头文件及开发环境的配置】:
Figure1:条件变量应用于多线程运行结果
(2)程序执行分析[wait与notify]
当不懂得一个程序运行的结果时,那就老老实实从最基本的机制用自己的脑袋将有必要的那部分程序运行一遍。我的笨方法。
- [1]两个线程不管哪一个先获取到互斥变量mu的“锁有权”,另一个线程的运行就会被阻塞。如线程th_2先获取到互斥变量mu的“锁有权”,那么就进入thread_fun_2内,此时th_1不拥有互斥变量的“锁有权”就会被其线程函数内的mu.lock()语句阻塞。
- [2]当thread_fun_2打印一次字符到屏幕之上后就会进入以 i%2为条件的while循环中执行”con_var_2.wait( mu);”语句。根据条件变量wait()函数的功能,th_2线程就会开始睡眠[就停留在”con_var_2.wait( mu );”语句处],同时wait(mu)函数还将unlock互斥量mu,在时刻mu.lock(mu)[等待锁定互斥量mu]的线程th_1立马获得互斥量的“锁有权”,然后开始执行线程th_1对应函数thread_fun_1内的内容[如果th_1内没有使用wait代码,那么此次线程th_1将会执行完毕,不是con_var_2.notify_one()函数一执行和th_2中con_var_2.wait()完成通信之后就会立即返回到th_2对应函数thread_fun_2中继续执行,而是会将th_1线程执行完之后再回到th_2(thread_fun_2)的con_var_2.wait()语句处 ,此时con_var_2.wait()函数返回,然后wait函数将再lock互斥变量mu。然后再判断while中的条件,如果条件为假则执行下一条语句,如果while中的条件依然为真,那么重新调用con_var_2.wait()函数继续等待]
- [3]当th_1d对应函数打印一个偶数数字到屏幕之后,进入while之中执行con_var_1.wait( mu )语句,由于此时线程th_2的”con_var_2.wait( mu );”已经收到过”con_var_1.notify_one();”的通信,所以th_2继续lock mu,然后执行下一段代码。在++i后,再通知th_1中的con_var_1.wait(mu )函数,等th_2再次发生等待时,th_1中的wait函数属性,重新锁定互斥变量mu,继续执行。如此反复执行代码,直到两个线程都执行完毕为止。
- [4]不过也发现了一个问题:两个线程初次使用notify_one()函数时,对方线程内都还没有使用过wait函数,那么notify_one()函数初次使用时是个什么状况?或许condition_variable_any在封装了处理这个问题的代码。I do not know now。
(3)条件变量封装机理[wait与notify]
其实这个机制在程序执行分析时已经完全的体现了。不过看起来挺长的样子,语言描述也不流畅。估计我今后也懒得看,还是整理一个比较简洁的版本来概括一下条件变量使用的机理。
- [1]条件变量类的使用体现在wait和notify_one两个函数之上
- [2]当在一个线程中用一个条件变量对象1调用wait函数时,它将起到暂时unlock多线程间供用的互斥变量而让本线程陷入等待之中。【由于对互斥变量的unlock,其它的线程会锁定互斥变量】,等其它线程执行完毕,再用条件变量对象1调用notify_one函数时,wait函数就会苏醒,并重新lock互斥变量,继续执行本线程。
总而言之,条件变量是一种逻辑控制,就是给咱提供了两个函数:wait函数用于发出信号并等待[还有unlock/lock机制],notify_one就是通知wait函数不用等了醒来返回吧。当在每个线程中都使用条件变量提供的这种机制时,逻辑上就比较复杂了,但是对于cpu来说很好分清,只要根据运行结果不断的调试,总会调到自己期望的逻辑效果。
3使用条件变量的基础
(1)纯粹的多线程运行
如果在程序中创建了多个线程,不使用互斥变量来约束各线程的运行顺序,那么当某个线程被定义时它就开始运行,在多线程的情况下,各线程以极短的时间交替运行着,可以认为在“同一时间”他们都在运行。
(2)使用互斥变量约束线程的运行
对于使用相同互斥变量的多个线程来说,只有获取到互斥量“锁有权”的线程才能运行,否则就会被阻塞直到获取到了互斥量的“锁有权”。所以,线程是被整个整个依次运行完毕的。而且很有可能是这样:不同时间的运行对应着不同次序的运行,获取互斥变量的顺序不同造成的。
(3)规定线程的运行顺序
在互斥变量的基础之上,使用条件变量就是能实现标题的内容。线程既不是“同时”运行也不是会因为运行环境的不同而造成各线程运行顺序的不同。
(1)~(3)是循序渐进的一个过程。
我想知道
mutex mu;
boost::mutex::scoped_lock lock(mu);和mu.lock()都能加锁,但不知有什么区别?
此次笔记记录完毕。
boost库(条件变量)的更多相关文章
- BOOST 条件变量使用
代码: // boost库 条件变量 使用测试 #include <iostream> #include <boost/thread.hpp> using namespace ...
- 并发编程(二):分析Boost对 互斥量和条件变量的封装及实现生产者消费者问题
请阅读上篇文章<并发编程实战: POSIX 使用互斥量和条件变量实现生产者/消费者问题>.当然不阅读亦不影响本篇文章的阅读. Boost的互斥量,条件变量做了很好的封装,因此比" ...
- 并发编程入门(二):分析Boost对 互斥量和条件变量的封装及实现生产者消费者问题
请阅读上篇文章<并发编程实战: POSIX 使用互斥量和条件变量实现生产者/消费者问题>.当然不阅读亦不影响本篇文章的阅读. Boost的互斥量,条件变量做了很好的封装,因此比" ...
- Boost条件变量condition_variable_any
Boost条件变量可以用来实现线程同步,它必须与互斥量配合使用.使用条件变量实现生产者消费者的简单例子如下,需要注意的是cond_put.wait(lock)是在等待条件满足.如果条件不满足,则释放锁 ...
- 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解
Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解 多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...
- Linux 下 boost 库的安装,配置个人环境变量
部分引自: https://blog.csdn.net/this_capslock/article/details/47170313 1. 下载boost安装包并解压缩到http://www.boos ...
- boost 条件变量
// boost 条件变量 // 做个简单的笔记 #include <boost/thread/mutex.hpp> #include <boost/thread/condition ...
- muduo网络库源码学习————条件变量
muduo里的CountDownLatch类实际上是对条件变量condition进行的封装,既可以用于所有子线程等待主线程发起 "起跑" ,也可以用于主线程等待子线程初始化完毕才开 ...
- boost 线程、互斥体、条件变量
1.任何技术都是针对特定场景设计的,也就是说,为了解决某个问题而设计的. 2.考虑下面一种场景:一个小旅馆,只有一个卫生间,有清洁人员,店主人,和旅客.卫生间用完之后,就会自动锁闭,必须取钥匙,才能进 ...
随机推荐
- Go cron定时任务的用法
cron是什么 cron的意思就是:计划任务,说白了就是定时任务.我和系统约个时间,你在几点几分几秒或者每隔几分钟跑一个任务(job),就那么简单. cron表达式 cron表达式是一个好东西,这个东 ...
- C语言 百炼成钢16
//题目46:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只 //猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五份,又多了 //一个,它同样把 ...
- Redis做消息队列文章两篇
介绍:http://www.cnblogs.com/lhfcws/p/3732535.html 具体做法:http://shift-alt-ctrl.iteye.com/blog/1867454 另外 ...
- Caffe学习系列(1):安装配置ubuntu14.04+cuda7.5+caffe+cudnn
一.版本 linux系统:Ubuntu 14.04 (64位) 显卡:Nvidia K20c cuda: cuda_7.5.18_linux.run cudnn: cudnn-7.0-linux-x6 ...
- HDU5336-XYZ and Drops-模拟
模拟水珠那个游戏. 小水珠超过边界会消失. 会有两个水珠同时到达一个size=4大水珠的情况.要移动完统一爆炸 #include <vector> #include <cstdio& ...
- 20145233韩昊辰 《Java程序设计》实验报告一:Java开发环境的熟悉(Windows+IDEA)
20145233 <Java程序设计>实验报告一:Java开发环境的熟悉 实验要求 使用JDK编译.运行简单的Java程序: 使用IDEA 编辑.编译.运行.调试Java程序. 实验内容 ...
- Orchard特性路线图(其实就是以后将做什么)
本文链接:http://www.cnblogs.com/souther/p/4539975.html 主目录 近期,我们将注意力集中在完成第一版的发布并且计划开发下一版.特征路线图提及的就是项目涉及到 ...
- Bootstrap系列 -- 28. 下拉菜单状态
下拉菜单项的默认的状态(不用设置)有悬浮状态(:hover)和焦点状态(:focus). 下拉菜单项除了上面两种状态,还有当前状态(.active)和禁用状态(.disabled).这两种状态使用方法 ...
- C#基础知识系列六(静态类和静态类成员)
静态类 静态类与非静态类基本相同,但存在一个区别:静态类不能实例化. 也就是说,不能使用 new 关键字创建静态类类型的变量. 因为没有实例变量,所以要使用类名本身访问静态类的成员. 例如,如果名为 ...
- 第三十九课:requestAnimationFrame详解
大家应该都知道,如果一个页面运行的定时器很多,无论你怎么优化,最后肯定会超过指定时间才能完成动画.定时器越多,延时越严重. 为此,YUI,kissy等采用中央队列的方式,将定时器减少至一个.浏览器厂商 ...