首先,引入一个概念叫做reorder,即重新安排。编译器编译出来的代码是一个黑盒子,标准对此的要求是,只要程序的行为在外观上相同即可。因此语句的reorder可能在单线程环境下并无问题,但是多线程组合以后,往往会改变预期的行为。
其次,单线程环境下,用条件判断获得的保证,在多线程中是失效的。比如if (container.empty() != true) doSomethingInContainer,这样的代码可能会在多线程环境中抛出异常,因为在通过if判断之后,对容器执行操作之前,可能会有其他线程修改容器,导致本来不为空(刚通过if判断时)的容器变成空的。正式因此这样的问题,才有了后来所谓的“double check”,既保证效率,又可以避免同时访问/修改数据。但是即使是double check也存在一些问题,比如上面的reorder就可能会破坏它的行为。
最后,线程可能访问的是写到半途的数据。比如有全局变量uint32_t value; 某个线程执行value = 0; 而另外一个线程读取value的值,那么可能读取的是写到一半(两个字节),还有另外一半未被写入的数据。所以,即使是基础类型,也不保证读或写是atomic。
原文:https://www.cnblogs.com/yxsrt/p/13023641.html