条件变量和无锁容器
Condition variables and lockfree container
条件变量使用互斥锁,.wait()函数解锁互斥,使另一个线程可以访问共享数据。当条件变量被通知试图再次锁定互斥锁以使用共享数据。
这个模式在下面Anthony Williams的concurrent_queue示例中使用:
template<typename Data>
class concurrent_queue
{
private:
boost::condition_variable the_condition_variable;
public:
void wait_for_data()
{
boost::mutex::scoped_lock lock(the_mutex);
while(the_queue.empty())
{
the_condition_variable.wait(lock);
}
}
void push(Data const& data)
{
boost::mutex::scoped_lock lock(the_mutex);
bool const was_empty=the_queue.empty();
the_queue.push(data);
if(was_empty)
{
the_condition_variable.notify_one();
}
}
};
由于代码使用了std::queue,很明显互斥锁必须是访问队列时被锁定。但是我们假设不是使用std::queue,而是使用microsoft并发::concurrent_queue from PPL。成员函数如empty,Push和try_pop是线程安全的。我还需要锁定互斥锁吗在这种情况下,条件变量可以这样使用吗创建任何可能的竞争条件
我的代码(这似乎可以工作,但这在多线程中意味着什么?)看起来像这样。我有一个生产者将项目推入microsoft concurrent_queue,还有一个后台线程等待该队列中的新项目。
消费者/后台线程:
while(runFlag) //atomic
{
while(the_queue.empty() && runFlag) //wait only when thread should still run
{
boost::mutex mtx; //local mutex thats locked afterwards. awkward.
boost::mutex::scoped_lock lock(mtx);
condition.wait(lock);
}
Data d;
while(!the_queue.empty() && the_queue.try_pop(d))
{
//process data
}
}
生产者/主线程:
const bool was_empty = the_queue.empty();
Data d;
the_queue.push(d);
if(was_empty) cond_var.notify_one();
关机程序:
bool expected_run_state = true;
if(runLoop.compare_exchange_strong(expected_run_state, false))
{
//atomically set our loop flag to false and
//notify all clients of the queue to wake up and exit
cond_var.notify_all();
}
如上所述,这段代码似乎工作,但这并不一定意味着它是正确的。特别是局部互斥锁,因为条件变量接口迫使我使用互斥锁,这似乎是一个非常糟糕的主意。我想使用条件变量,因为添加到队列中的数据项之间的时间很难预测,并且我必须像这样周期性地创建睡眠和唤醒:
if(the_queue.empty()) Sleep(short_amount_of_time);
有没有其他的,也许是操作系统(在我的情况下:Windows)特定的工具,使后台线程睡眠,直到某些条件满足,没有定期唤醒和检查条件?
代码在不同的场景下是不正确的,例如。如果在计算const bool was_empty = the_queue.empty();
时队列中只有一个元素,但是一个线程正在消耗该元素,而另一个线程试图消耗该元素并等待该条件,则写入器在将元素插入队列后不会通知该线程。
有没有其他的,也许是操作系统(在我的情况下:Windows)特定的工具,这会使后台线程休眠,直到满足某些条件没有定期醒来检查情况吗?
这就是事件的作用
但如果你只针对Windows平台(Vista+),你应该查看
精简读写器(SRW)锁
- 基于模板值的条件变量
- 没有超时的C++条件变量
- 在条件变量中触发错误信号的频率是多少
- 使用不变量来确定二分搜索中的边界条件
- 在通知提升间处理条件变量时未按住锁会导致问题
- 通知条件变量后使用互斥锁
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 滥用条件变量
- 升压插值条件变量可以虚假唤醒吗?
- 根据模板类型有条件地删除变量
- 子线程中的条件变量等待停止主线程中的执行
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 条件变量基本示例
- 正在连接的等待条件变量的线程会发生什么情况?
- C++11如何在1个线程中使用条件变量处理2个线程安全队列
- 当线程处理不同的类时,应该在哪里声明条件变量、互斥对象
- 为什么在同一条件变量上使用多个互斥锁会使此代码崩溃?
- 条件变量:wait_for.gcc错误
- 如何"stop"正在等待条件变量的分离线程?
- 调用一个小函数两次(例如在if条件和主体中)比将结果存储在局部变量中更可取