我知道当多个线程正在读写变量时,atomic将对“ T”类型的变量施加锁定,以确保其中只有一个正在执行R / W。
但是在多核CPU中,线程可以在不同的内核上运行,并且不同的内核将具有不同的L1缓存,L2缓存,而共享L3缓存。我们知道,有时C ++编译器会优化变量以存储在寄存器中,因此,如果变量未存储在内存中,则该变量的不同核心高速缓存之间就不会出现内存同步。
所以我的担心/问题是,如果原子变量被编译器优化为某个寄存器变量,那么它就不会存储在内存中,当一个内核写入其值时,另一个内核会读出一个过时的值,对吗?这样的数据一致性有保证吗?
谢谢。
答案 0 :(得分:3)
原子不会按照您隐约描述的方式“解决”问题。它为基于顺序的内存一致性提供了某些非常具体的保证。
各种编译器在不同平台上以不同方式实现这些保证。
在x86 / 64上,没有锁用于原子整数和不超过合理大小的指针。而且硬件提供了比标准要求更强的保证,使某些更深奥的选择等同于完全一致性。
我无法完全回答您的问题,但我可以为您指明正确的方向;您需要学习的主题是“ C ++内存模型”。
话虽如此,原子的存在是为了避免您所描述的确切问题。如果您要求完全的内存顺序一致性,并且线程A修改了X,然后修改了Y,则其他线程看不到Y修改,但X则修改不了。C ++标准未指定如何提供保证;缓存行无效,使用特殊指令进行访问,禁止编译器进行某些基于寄存器的优化等,都是编译器所做的事情。
请注意,C ++内存模型已针对C ++ 17进行了改进,错误修复和完善,以描述新的并行算法的行为,并允许它们在带有正确标志的GPU硬件上(以及其他地方)高效实现,并且反过来又影响了新GPU硬件提供的保证。因此,谈论内存模型的人们可能会感到兴奋,并谈论比您主要的C ++ 11更关注的现代问题。
这是一个复杂的大话题。编写您认为可移植的代码确实很容易,但是它们只能在特定平台上运行,或者通常只能在您对其进行测试的平台上运行。但这仅仅是因为线程很难。
答案 1 :(得分:2)
您可能正在寻找这个:
[intro.progress] / 18 ,实现应确保原子或同步操作分配的最后一个值(按修改顺序)在有限的时间内对所有其他线程可见