如果没有在互斥对象下修改共享原子变量,则不能正确发布
Shared atomic variable is not properly published if it is not modified under mutex
我正在阅读http://en.cppreference.com/w/cpp/thread/condition_variable上的std::condition_variable,我不明白这个:
即使共享变量是原子的,也必须在互斥,以便正确地将修改发布到等待中线程。
为什么一个共享原子变量在互斥下没有被修改就不能正确发布?如何理解这句话呢?
在另一页http://en.cppreference.com/w/cpp/atomic/atomic有一个语句似乎与第一个语句相矛盾:
如果一个线程写一个原子对象,而另一个线程读从它,行为是定义良好的(参见内存模型的详细信息数据竞争)
考虑这个例子:
std::atomic_bool proceed(false);
std::mutex m;
std::condition_variable cv;
std::thread t([&m,&cv,&proceed]()
{
{
std::unique_lock<std::mutex> l(m);
while(!proceed) {
hardWork();
cv.wait(l);
}
}
});
proceed = true;
cv.notify_one();
t.join();
这里原子共享数据proceed
在没有使用互斥锁的情况下被修改,然后通知发送给条件变量。但有可能在通知发送的那一刻,线程t
没有等待cv
:相反,它在hardWork()
内部,在此之前检查了proceed
,发现它是假的。通知丢失。当t
完成hardWork
时,它将恢复等待(大概是永远)。
如果主线程在修改共享数据proceed
之前锁定了互斥锁,这种情况就可以避免了。
我认为这就是"即使共享变量是原子的,也必须在互斥锁下修改它,以便正确地将修改发布到等待线程"时的情况。
相关文章:
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 表达式必须具有常数值,变量不能用作定义数组大小的常数
- 变量不能明确
- 流变量不能出现在 OpenMP 第一私有中?
- 为什么 UInt64 变量不能包含大于 UInt32::Max 的值?
- 变量不能在 lambda 中隐式捕获,并且没有使用 switch 语句指定捕获默认值
- 什么形式上保证了非原子变量不能看到凭空出现的值,并像理论上原子一样创造数据竞赛?
- 为什么可以将Char指针变量初始化为字符串,而INT指针变量不能初始化到整数数组
- clang vs gcc CRTP:constexpr 变量不能有非文字类型
- 为什么这些变量不能移动?
- 为什么我的基类指针变量不能访问派生类中的函数?
- 变量不能出现在常量表达式中
- 哪些临时变量不能在 c++11 中使用“someType()”初始化
- 为什么除了直接赋值0之外,bool变量不能设置为0
- 常量变量不能是引用的模板参数,但非常量可以
- WARN:变量不能绑定(它要么不存在,要么已经被优化掉了)
- 整型变量不能存储大的值
- 变量不能在没有指定capture-default的lambda中隐式捕获
- 变量不能产生正确的数据