对“关于boost::condition的用法”文章的个人的分析
2011-08-13 08:34
288 查看
首先我们看只有一个reader/一个writer的情形
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;
void writer()
{
while (1) {
boost::mutex::scoped_lock sl(m);
if (number == 5) {
not_full.wait(m);
}
++number;
std::cout << "after w: " << number << std::endl;
not_empty.notify_one();
}
}
void reader()
{
while (1) {
boost::mutex::scoped_lock sl(m);
if (number == 0) {
not_empty.wait(m);
}
--number;
std::cout << "after r: " << number << std::endl;
not_full.notify_one();
}
}
void main()
{
boost::thread trd1(&writer);
boost::thread trd2(&reader);
trd1.join();
trd2.join();
}
运行之后程序一切如常,0-5的一些数字会打印出来。
但是当另外一个write加入战局的时候,情况变得有些微妙的不同,如果我们只是在main里面加入一个writer,其他部分保持不变的话,你会看到一些错误的数字出现:
void main()
{
boost::thread trd1(&writer);
boost::thread trd11(&writer);
boost::thread trd2(&reader);
trd1.join();
trd11.join();
trd2.join();
}
究其原因是:在reader->notify_one之后并在socped_lock解锁之前,在not_full上等待的writer A被唤起,然后reader解锁,此时可能另外一个writer B先获得锁而直接增加了number。在writeB 解锁后, writerA获得锁,但此时not_full条件已经被破坏。所以一种做法是再次检查该条件,也就是这样:
while (number == 5) {
not_full.wait(m);
}
对于多write或多reader的情形也是一样都需要以一个while循环进行conditiond的复检:完整的代码如下
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;
void writer()
{
while (1) {
boost::mutex::scoped_lock sl(m);
while (number == 5) {
not_full.wait(m);
}
++number;
std::cout << "after w: " << number << std::endl;
not_empty.notify_one();
}
}
void reader()
{
while (1) {
boost::mutex::scoped_lock sl(m);
while (number == 0) {
not_empty.wait(m);
}
--number;
std::cout << "after r: " << number << std::endl;
not_full.notify_one();
}
}
void main()
{
boost::thread trd1(&writer);
boost::thread trd11(&writer);
boost::thread trd2(&reader);
boost::thread trd22(&reader);
trd1.join();
trd11.join();
trd2.join();
trd22.join();
}
看了上面的文章,尽管有作者的解释,但还是没看明白。
经过不断的思考,才理解了boost::condition .wait为什么需要放在一个循环里
下面是我个人比较详细的分析。
比如有write A,write B和reader.
某个时刻,number等于5,并且在运行write A,write A阻塞在了wait函数上(这时会释放锁m),然后有可能reader开始运行,使number等于4,随后通过not_full.notify_one唤醒了write A,write A准备获取锁(write B也在等待获取锁),reader释放锁,由于线程运行的不确定性,这时有可能write B首先获取了锁使得number又等于5了。write B运行完毕释放锁,write A获得锁往下运行++number; 此时number等于6了,不在0和5范围内了。
如果write A获得锁后,通过while再检查一遍number,发现number等于5,就会又阻塞在wait函数上。这样一来,就能得到预期的结果了。
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;
void writer()
{
while (1) {
boost::mutex::scoped_lock sl(m);
if (number == 5) {
not_full.wait(m);
}
++number;
std::cout << "after w: " << number << std::endl;
not_empty.notify_one();
}
}
void reader()
{
while (1) {
boost::mutex::scoped_lock sl(m);
if (number == 0) {
not_empty.wait(m);
}
--number;
std::cout << "after r: " << number << std::endl;
not_full.notify_one();
}
}
void main()
{
boost::thread trd1(&writer);
boost::thread trd2(&reader);
trd1.join();
trd2.join();
}
运行之后程序一切如常,0-5的一些数字会打印出来。
但是当另外一个write加入战局的时候,情况变得有些微妙的不同,如果我们只是在main里面加入一个writer,其他部分保持不变的话,你会看到一些错误的数字出现:
void main()
{
boost::thread trd1(&writer);
boost::thread trd11(&writer);
boost::thread trd2(&reader);
trd1.join();
trd11.join();
trd2.join();
}
究其原因是:在reader->notify_one之后并在socped_lock解锁之前,在not_full上等待的writer A被唤起,然后reader解锁,此时可能另外一个writer B先获得锁而直接增加了number。在writeB 解锁后, writerA获得锁,但此时not_full条件已经被破坏。所以一种做法是再次检查该条件,也就是这样:
while (number == 5) {
not_full.wait(m);
}
对于多write或多reader的情形也是一样都需要以一个while循环进行conditiond的复检:完整的代码如下
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;
void writer()
{
while (1) {
boost::mutex::scoped_lock sl(m);
while (number == 5) {
not_full.wait(m);
}
++number;
std::cout << "after w: " << number << std::endl;
not_empty.notify_one();
}
}
void reader()
{
while (1) {
boost::mutex::scoped_lock sl(m);
while (number == 0) {
not_empty.wait(m);
}
--number;
std::cout << "after r: " << number << std::endl;
not_full.notify_one();
}
}
void main()
{
boost::thread trd1(&writer);
boost::thread trd11(&writer);
boost::thread trd2(&reader);
boost::thread trd22(&reader);
trd1.join();
trd11.join();
trd2.join();
trd22.join();
}
看了上面的文章,尽管有作者的解释,但还是没看明白。
经过不断的思考,才理解了boost::condition .wait为什么需要放在一个循环里
下面是我个人比较详细的分析。
比如有write A,write B和reader.
某个时刻,number等于5,并且在运行write A,write A阻塞在了wait函数上(这时会释放锁m),然后有可能reader开始运行,使number等于4,随后通过not_full.notify_one唤醒了write A,write A准备获取锁(write B也在等待获取锁),reader释放锁,由于线程运行的不确定性,这时有可能write B首先获取了锁使得number又等于5了。write B运行完毕释放锁,write A获得锁往下运行++number; 此时number等于6了,不在0和5范围内了。
如果write A获得锁后,通过while再检查一遍number,发现number等于5,就会又阻塞在wait函数上。这样一来,就能得到预期的结果了。
相关文章推荐
- 对“关于boost::condition的用法”文章的个人的分析
- 个人总结的一些关于String、Function、Array的属性和用法
- 本博客中关于功能点分析FPA的文章索引
- 一篇关于delphi的TThread分析的文章,很有深度
- 新辰:关于个人网站安全问题的分析及对策探讨
- 关于需求分析与系统设计的文章
- 关于JQuery($.load)事件的用法和分析
- 关于JQuery($.load)事件的用法和分析
- 关于CNNIC开放个人注册cn域名对域名市场影响的分析
- 一组关于需求分析的文章
- 关于ReentrantLock和Condition的用法
- boost::condition的用法
- 转帖两篇关于ACE和boost::asio的文章
- 关于jQuery中noConflict()用法分析(转)
- 关于cliptopadding用法(仅限于个人收藏)
- 个人总结的一些关于String、Function、Array的属性和用法
- 今天看到的关于activity四种启动模式分析的文章(standard、singleTop、singleTask、singleInstance)
- asp.net中关于&lt;% %&gt;、&lt;%= %&gt;的用法——个人总结
- 关于SetCapture() 和 ReleaseCapture()的用法的个人理解
- 转载一篇关于java内存分析的文章!