升压条件变量

Boost condition variable

本文关键字:变量 条件      更新时间:2023-10-16

我想使用boost条件变量作为同步机制,但是在这种情况下:

boost::condition_variable cond;
boost::mutex              mutex;
void worker_func()
{
    cond.notify_all();
    std::cout << "After notify" << std::endl;
}
void main()
{
    boost::mutex::soped_lock lock(mutex);
    boost::thread work(worker_func);
    boost::this_thread::sleep_for(boost::chrono::milliseonds(500));
    cond.wait(lock); // here is deadlock
}

当我们在等待条件之前触发条件时,就会发生死锁。如果有一个很好的解决方案来编写包装器,提供bool原子,"记住"先前触发的条件,或者有其他更好的方法来做到这一点?

包装器示例:

class Cond_wrap
{
private:
    boost::condition_variable cond;
    boost::mutex              mutex;
    bool work_to_do;
public:
    Cond_wrap()
    {
        boost::mutex::scoped_lock(mutex);
        work_to_do = false; 
    }
    void notify_all()
    {
        boost::mutex::scoped_lock(mutex);
        work_to_do = true;
        cond.notify_all();
    }
    void wait()
    {
        boost::mutex::scoped_lock lock(mutex);
        if(!work_to_do)
        {
            cond.wait(lock);
            work_to_do = true;
        }
        else
        {
            return;
        }
    }
    bool timed_wait(unsigned int timeout)
    {
        boost::mutex::scoped_lock lock(mutex);
        if(!work_to_do)
        {
            if(cond.timed_wait(lock, boost::chrono::milliseonds(timeout)))
            {
                work_to_do = true;
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
};
Cond_wrap condition_wrap;
void worker_func()
{
    {
        condition_wrap.notify_all();
    }
    std::cout << "After notify" << std::endl;
}
int main()
{
    boost::thread work(worker_func);
    work.detach();
    {
        boost::this_thread::sleep_for(boost::chrono::milliseonds(500));
        condition_wrap.wait();
        //there is work to do
    }
    return 0;
}

条件变量不是这样工作的。条件变量应该有一个相关联的条件。这个条件是在持有互斥锁的情况下求值的,因此不可能出现竞争,因此不需要等待。

请注意,此条件还需要考虑虚假唤醒的可能性。

还应该从持有锁的线程通知条件变量。在锁被持有的情况下生成新线程可能不是一个好主意。我喜欢用大括号来清楚地说明锁定代码的作用域。

boost::condition_variable cond;
boost::mutex              mutex;
bool work_to_do = false;
void worker_func()
{
    {
        boost::mutex::scoped_lock lock(mutex);
        work_to_do = true,
        cond.notify_all();
    }
    std::cout << "After notify" << std::endl;
}
int main()
{
    boost::thread work(worker_func);
    {
        boost::mutex::scoped_lock lock(mutex);
        boost::this_thread::sleep_for(boost::chrono::milliseonds(500));
        while (!work_to_do)
            cond.wait(lock); // no deadlock
        //there is work to do
        work_to_do = false;
    }
}

请注意,在我的代码中,work_to_do变量总是与持有的锁一起使用,对notify_all()的调用也是如此。另外,请注意cond.wait()是在循环中调用的,因此虚假的唤醒不会破坏乐趣。

p。对void main()说不

与windows事件不同,条件变量没有任何状态,因为它是用于等待和通知的机制。也可能有虚假的唤醒。

必须将一些状态与条件变量关联起来。示例见http://en.cppreference.com/w/cpp/thread/condition_variable。

要使用条件变量,需要具备3个条件:

条件变量、互斥锁和变量。

操作其他两个元素时,锁住互斥锁。

当你想发送消息给等待者时,锁定互斥锁,设置变量,然后使用条件变量通知。(在某些情况下,在notify: check your docs之前解锁互斥锁)

当你想要获取消息时,锁定互斥锁,检查变量,等待条件。可能会有虚假的唤醒(请检查您的文档),所以当您唤醒时请重新检查变量。

这是基于c++ 11 std条件变量的知识,因此有"check your docs"注释。