您的位置:首页 > 其它

对“关于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函数上。这样一来,就能得到预期的结果了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: