boost condition

 1.简介
condition是一个简单的同步对象,用于使一个线程等待一个特定的条件成立(比如
资源可用)。一个condition对象总是和一个mutex对象配合使用。mutex在交给condition
对象的wait系列函数时,必须已经通过lock对象加上了锁。当线程陷入等待时,condtion
对象将释放mutex上的锁,当wait返回时,mutex上的锁会重新加上,这一unlock/lock
动作由conditon对象自动完成。

2.使用
namespace boost
{
    class condition : private boost::noncopyable // Exposition only.
       // Class condition meets the NonCopyable requirement.
    {
    public:
        condition();
        ~condition();

        void notify_one();
//      唤起等待队列中的一个线程
        void notify_all();
//      唤起等待队列中的所有线程
        template <typename Lock> void wait(Lock& lock);
//      ScopedLock 是一个lock对象,符合ScopedLock 概念
//      释放lock中mutex上的锁,阻塞该线程,直到任何人调用了this->notify_one()或
//      this->notify_all(),然后重新lock mutex。
        template <typename Lock, typename Predicate>
            void void wait(Lock& lock, Predicate pred);
//      ScopedLock 是一个lock对象,符合ScopedLock 概念
//      相当于while (!pred()) wait(lock)。
        template <typename Lock>
            bool timed_wait(Lock& lock, const xtime& xt);
//      wait(Lock& lock)的限时版,当XT到达时,函数返回false,当因notify而返回时
//      函数返回true
        template <typename Lock, typename Predicate>
            bool timed_wait(Lock& lock, const xtime& XT, Predicate pred);

//      wait(Lock& lock, Predicate pred)的限时版,当XT到达时,函数返回false,当
//      因notify和pred而而返回时函数返回true
    };
};

3.例子
一个经典的消息队列的实现
#include <iostream>
#include <vector>
#include <boost/utility.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>

class bounded_buffer : private boost::noncopyable
{
public:
    typedef boost::mutex::scoped_lock lock;

    bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }

    void send (int m) { //      加入消息
        lock lk(monitor);
        while (buffered == circular_buf.size())
            buffer_not_full.wait(lk);
        circular_buf[end] = m;
        end = (end+1) % circular_buf.size();
        ++buffered;
        buffer_not_empty.notify_one();
    }
    int receive() {     //      取走消息
        lock lk(monitor);
        while (buffered == 0)
            buffer_not_empty.wait(lk);
        int i = circular_buf[begin];
        begin = (begin+1) % circular_buf.size();
        --buffered;
        buffer_not_full.notify_one();
        return i;
    }

private:
    int begin, end, buffered;
    std::vector<int> circular_buf;
    boost::condition buffer_not_full, buffer_not_empty;
    boost::mutex monitor;
};

 

 

我这里只讨论boost::condition在reader/writer模式中的一些注意点

首先我们看只有一个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();
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值