是 std::condition_variable 线程安全的
Is std::condition_variable thread-safe?
我有一些这样的代码:
std::queue<myData*> _qDatas;
std::mutex _qDatasMtx;
发电机功能
void generator_thread()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
{
std::lock_guard<std::mutex> lck(_qDatasMtx);
_qData.push(new myData);
}
//std::lock_guard<std::mutex> lck(cvMtx); //need lock here?
cv.notify_one();
}
消费者功能
void consumer_thread()
{
for(;;)
{
std::unique_lock lck(_qDatasMtx);
if(_qDatas.size() > 0)
{
delete _qDatas.front();
_qDatas.pop();
}
else
cv.wait(lck);
}
}
因此,如果我有几十个生成器线程和一个消费线程,在每个线程中调用 cv.notify_one() 时是否需要互斥锁?
std::condition_variable线程安全吗?
在每个线程中调用
cv.notify_one()
时是否需要mutex
锁?
不
std::condition_variable
线程安全吗?
是的
调用wait
时,您会传递一个锁定的mutex
该该立即解锁以供使用。调用notify
时,您不会使用相同的mutex
锁定它,因为将要发生的事情(在链接中详细说明):
- 通知
- 正在等待的唤醒线程
- 锁定互斥锁以供使用
从std::condition_variable
:
在 std::condition_variable 上执行notify_one或notify_all(无需按住锁定进行通知)
和从std::condition_variable::notify_all
:
通知线程不需要将锁与等待线程持有的锁锁保持在同一互斥锁上;
关于您的代码片段:
//std::lock_guard<std::mutex> lck(cvMtx); //need lock here?
cv.notify_one();
不,你不需要那里的锁。
notify_one
可以从多个线程调用,而无需锁定。
但是,为了使正常操作正常工作并且没有通知"溜走"的机会,您必须在修改虚假唤醒保护和/或打包条件变量检查读取的点和通知一个点之间锁定条件变量
。您的代码似乎通过了该测试。 但是,此版本更清晰:
std::unique_lock lck(_qDatasMtx);
for(;;) {
cv.wait(lck,[&]{ return _qDatas.size()>0; });
delete _qDatas.front();
_qDatas.pop();
}
它减少了虚假解锁/重新锁定。
相关文章:
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 如何以线程安全的方式更改目录?
- 线程安全的引用计数队列C++
- 析构函数和线程安全
- 适用于大型数组的无复制线程安全环形缓冲区