BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #81371同步于 2014/8/7
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

[多线程毁三观]1.穿越时空

nuanyangyang
2014/8/7镜像同步54 回复
下面的程序,为什么有时候会读到r1和r2都是1?明明按任何顺序交错执行都不能出现这种结果的,难道程序可以穿越到未来去读到未来的结果? //不要简单地说“有data race的程序都是未定义行为,什么都可能发生”,尽管这是事实,data race在C语言里就是未定义行为,真的什么都可能发生,从什么也不发生到机器冒烟都可能。但起码给出一个“为什么会发生”的解释。 若不加说明,所有的例子都是C++11(新标准)。 #include <cstdio> #include <thread> int x = 0; int y = 0; void thr1() { int r1 = x; y = 1; std::printf("r1 = %d\n", r1); } void thr2() { int r2 = y; x = 1; std::printf("r2 = %d\n", r2); } int main(int argc, char *argv[]) { std::thread t1(thr1); std::thread t2(thr2); t1.join(); t2.join(); return 0; } 为了避免争议,解释一下:上述程序是错误的。原因是两个线程中,存在冲突(conflict)的内存访问: 1、读写冲突: r1=x 和 x=1 2、读写冲突: r2=y 和 y=1 而冲突的读和写又没有任何同步(加锁,或者使用原子内存操作),故它们之间不存在happen-before关系。没有happen-before关系的冲突访问就是data race。data race在C11和C++11语言中是未定义行为(undefined behaviour),编译器可以假设这种事情不会发生,但如果真的发生了,则允许产生任何后果,从什么也没发生到机器冒烟都是允许的。
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
FromMars机器人#1 · 2014/8/7
有没有可能是std::printf("r2 = %d\n", r2); 这句话执行的时间较长?
nuanyangyang机器人#2 · 2014/8/7
【 在 FromMars 的大作中提到: 】 : 有没有可能是std::printf("r2 = %d\n", r2); 这句话执行的时间较长? 不是。和printf都没有关系,只是为了打印出来便于观看。其实r2,r1早就都是1了。
wangxiaobupt机器人#3 · 2014/8/7
我怎么没试出来都为1的 由于标准输出不是线程安全的 我打印出来的都是很混乱的 = =
FromMars机器人#4 · 2014/8/7
为啥我刚刚运行好多次,都没出现过都是1的情况== 【 在 nuanyangyang 的大作中提到: 】 : 不是。和printf都没有关系,只是为了打印出来便于观看。其实r2,r1早就都是1了。
FromMars机器人#5 · 2014/8/7
还跟着个有关?我怎么觉得仅仅因为线程争取cpu时间先后顺序-- 【 在 wangxiaobupt 的大作中提到: 】 : 我怎么没试出来都为1的 : 由于标准输出不是线程安全的 我打印出来的都是很混乱的 = = :
wangxiaobupt机器人#6 · 2014/8/7
跟这个没关 只是我在测试的时候 结果都是些混乱的东西 不过总有一个0一个1 【 在 FromMars 的大作中提到: 】 : 还跟着个有关?我怎么觉得仅仅因为线程争取cpu时间先后顺序--
FromMars机器人#7 · 2014/8/7
怎么混乱发咧? 我的运行结果一直是先0后1 等大神出解释,学习好了== 【 在 wangxiaobupt 的大作中提到: 】 : 跟这个没关 只是我在测试的时候 结果都是些混乱的东西 不过总有一个0一个1 :
nuanyangyang机器人#8 · 2014/8/7
标准允许这种行为,但是不一定能重现,即使能,也很难重现。
gaoweiwei机器人#9 · 2014/8/7
乱序执行了吧?关掉优化试试 【 在 nuanyangyang 的大作中提到: 】 : 下面的程序,为什么有时候会读到r1和r2都是1?明明按任何顺序交错执行都不能出现这种结果的,难道程序可以穿越到未来去读到未来的结果? : //不要简单地说“有data race的程序都是未定行为,什么都可能发生”,尽管这是事实,真的什么都可能发生,从什么也不发生到机器冒烟都可能。但起码给出一个“为什么会发生”的解释。 : 若不加说明,所有的例子都是C++11(新标准)。 : ...................