我想使用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 atomic,它记得&#39;这个条件以前被解雇了还是有其他更好的方法来做到这一点?
包装器示例:
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;
}
答案 0 :(得分:3)
条件变量的工作原理并非如此。条件变量应该具有关联的条件。这个条件是在持有互斥锁的情况下评估的,因此不可能进行比赛,因此您不需要等待。
请注意,虚假唤醒的可能性也需要这种情况。
还应该从持有锁的线程通知条件变量。并且保持锁定生成新线程可能不是一个好主意。我想添加大括号以明确说明锁定代码的范围。
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()
在循环中被调用,因此虚假的唤醒不会破坏乐趣。
PS。只对void main()
说不。
答案 1 :(得分:1)
与Windows事件不同,条件变量没有任何状态,因为它是用于等待和通知的机制。也可能有虚假的叫醒。
您必须将某个状态与条件变量相关联。请参阅http://en.cppreference.com/w/cpp/thread/condition_variable上的示例。
答案 2 :(得分:0)
要使用条件变量,您需要3件事。
条件变量,互斥锁和变量。
在对其他两个元素进行操作时,锁定互斥锁。
如果要向服务员发送消息,请锁定互斥锁,设置变量,然后使用条件变量进行通知。 (在某些情况下,在通知之前解锁互斥:检查你的文档)
如果要获取消息,请锁定互斥锁,检查变量,然后等待条件。虚假的唤醒可能是可能的(检查你的文档),所以当你醒来时重新检查变量。
这是基于C ++ 11 std
条件变量的知识,因此“检查你的文档”注释。