为啥这段代码会导致data race?

在现代的编译器和 CPU 上,为了提高性能,真正的执行顺序和高级语言中的已经不一致了。双重检查也不例外。编译器生成的机器码会对内存读写指令进行重新排序,CPU 的乱序执行会进一步改变内存读写指令的执行顺序。因为有了这些乱序的存在,instance = new T 这一行并不能一次执行完。比如,instance = new T 可以分解成 3 个操作,申请内存、赋值给 instance、调用构造函数。后两个操作是以什么方式进行的,只有编译器能决定。如果先赋值给是,再调用构造函数,那么另一个线程同时调用了 Singleton() 的话,就会发现 instance 已经有值了,直接使用。但因为这时候还没有在 instance 上调用构造函数,对象还没被建立出来,这样就会引发严重的问题。转自下面这篇文章C++中线程安全并且高效的singleton
■网友
C++11的最简实现:Double-Checked Locking is Fixed In C++11Singleton\u0026amp; Singleton::getInstance() { static Singleton instance; return instance;}The C++11 standard’s got our back in §6.7.4:
【为啥这段代码会导致data race?】 If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

■网友
编译器有可能reordering,导致另一个线程访问出错resource_ptr.reset(new some_resource); // !参见meyers的解释:http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdfc++11 使用atomic可解决这个问题: 可参见herb sutter 的这个talkCppCon2014/Lock-Free Programming (or, Juggling Razor Blades)
■网友
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
■网友
这种情况可以用std::call_once 和 std::call_flag 解决


    推荐阅读