在我的代码中,一些并发工作任务应该仅在特殊事件未处于信号状态时才开始工作。 代码示例:
tasks.run([&](){
if (event.wait(0)!=0)
{
event.set();
// work code ...
}
})
这样的任务可能有很多实例,只有一个应该工作。但是wait()和set()是不同的方法,代码不是原子的。因此,可能是两个或更多任务实例开始工作的情况。 我如何测试事件的信号状态并仅在它没有信号时锁定它,并以原子方式进行?
答案 0 :(得分:1)
您似乎可以使用mutex::try_lock
代码应如下所示:
tasks.run([&](){ if (event.wait(0)!=0 && mutex.try_lock()) { event.set(); mutex.unlock(); // work code ... } })
不要忘记确保event.set()不会抛出异常,否则需要额外的努力才能使此代码异常安全。
可能是你应该把整个包裹起来(true)来捕捉'假阳性'的情况,就像那样:
tasks.run([&](){ while(true) { if (event.wait(0)!=0 && mutex.try_lock()) { event.set(); mutex.unlock(); // work code ... break; } } });
因此未能获得锁定的任务将返回等待状态。
答案 1 :(得分:0)
我的解决方案:
安全设置事件类:
namespace Concurrency {
class event_safe : public event
{
public:
inline bool try_set()
{
critical_section::scoped_lock locker(m_lock);
bool bRes = (wait(0)==Concurrency::COOPERATIVE_WAIT_TIMEOUT);
if (bRes)
set();
return bRes;
}
protected:
critical_section m_lock;
};
}
工作代码:
tasks.run([&](){
if (event.try_set()) {
// work code ...
}
})