我正在使用C ++ 11,其中有4个并行插入并发队列的线程。我知道线程何时完成处理,即队列的预期最终大小。
现在,我想对队列内容执行最终聚合操作,该队列内容应严格 仅执行一次。例如,假设我想聚合这些值并将其POST到外部服务。
如何获取仅有效一次的锁定?我不能使用简单的互斥锁,因为这不能保证我只能使用一次。
伪代码:
// inside a thread
enqueue items to concurrent_queue
if(concurrent_queue.size() == EXPECTED_SIZE) {
// do something ONLY once
}
答案 0 :(得分:7)
一个简单的解决方案。
if(concurrent_queue.size() == EXPECTED_SIZE) {
// do something ONLY once
static bool doItOnce = DoItOnceOnly();
}
答案 1 :(得分:2)
检查Singleton实现的方法。最基本的:
bool executed = false;
void Execute()
{
Lock lock; // scope-based lock, released automatically when the function returns
if (executed == false)
{
executed = true;
//.. do computation
}
}
检查具有原子变量的解决方案和双重检查锁定以获得更好的性能: http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
答案 2 :(得分:2)
如果您不担心操作失败的可能性,您只需使用与操作相关联的atomic<bool>
即可。所有主题都会尝试使用compare_exchange_strong将标记从false
更改为true
,但只有一个会成功:
// inside a thread
enqueue items to concurrent_queue
if(concurrent_queue.size() == EXPECTED_SIZE) {
std::atomic<bool>& flag = retrieve_the_associated_bool();
bool expected = false;
if (flag.compare_exchange_strong(expected, true)) {
// do something
}
}
如果操作失败,您应该使用std::call_once
和与该操作相关联的std::once_flag
。其他线程会在尝试“做某事”时等待,并且每个线程依次尝试直到成功:
// inside a thread
enqueue items to concurrent_queue
if(concurrent_queue.size() == EXPECTED_SIZE) {
std::once_flag& flag = retrieve_the_associated_once_flag();
std::call_once(flag, []{
// do something
});
// do something ONLY once
}