返回信息流请问下面的程序为什么有时候r1和r2的值会不一样?不要简单地说程序是未定义行为,虽然这是事实,确实有data race,确实是未定义行为,任何事都允许发生,从什么都不发生到电脑冒烟都是允许的。但能不能给出一个为什么会发生的原因呢?
需要C++11
#include <cstdio>
#include <atomic>
#include <thread>
#include <mutex>
int x;
std::mutex m1, m2;
void func1() {
m1.lock();
x = 1;
m1.unlock();
}
void func2() {
m2.lock();
x = 2;
m2.unlock();
}
void func3() {
m1.lock();
m2.lock();
int r1 = x;
int r2 = x;
m2.unlock();
m1.unlock();
std::printf("r1 = %d, r2 = %d\n", r1, r2);
}
int main() {
std::thread t1(func1);
std::thread t2(func2);
std::thread t3(func3);
t1.join();
t2.join();
t3.join();
return 0;
}
为了避免争议,解释一下,上述程序是错误的。这两个锁很“画蛇添足”,前两个线程可以分别加锁,中间对x根本不是互斥访问的。换句话说,线程1和线程2对x的两个写之间不存在happen-before关系,故引发data race。在C++11中,data race是未定义行为,任何事都允许发生,从什么都不发生到电脑冒烟都是允许的。
这是一条镜像帖。来源:北邮人论坛 / cpp / #81434同步于 2014/8/9
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
[多线程毁三观]2.画蛇添足
nuanyangyang
2014/8/9镜像同步15 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
【 在 zx723 的大作中提到: 】
: 个人觉得讨论这个问题的时候,不说明Consistency Model,就没法讨论了
C++11 memory model
去翻一翻Hans Boehm的论文吧,他是这方面的专家。
【 在 gaoweiwei 的大作中提到: 】
: 暖神开个这个方面的专题帖吧,让我们学习学习
来自「北邮人论坛手机版」
嗯。这个解释还是可以的。
不过,具体实现的可能比标准定义的严格。但除非某个实现的文档告诉你这个行为可依赖,否则还是不能依赖。
【 在 iFadeToBlack 的大作中提到: 】
: 大概是1和2的写没有立即写回内存,使对3可见
: 还需要查lock的实现验证一下,明天再说
来自「北邮人论坛手机版」
【 在 tonyjansan 的大作中提到: 】
: 这个程序写法太粗暴了,全局变量没初始化并且压栈、锁操作过于繁琐了。
选自一篇论文,讨论的是一些异常情形。毕竟这个程序是错误的。有可能是从更复杂的程序里提取出来的简单代码,把中间复杂的运算抽象掉了,专门来指明错误。
不过全局变量按规定是要初始化成0的(除非有构造函数),这倒不是问题。