
假设线程1(在Core0中执行)更新一个全局变量,更新后的全局值被缓存在Core0的L1缓存中(而不是刷新到主内存)。然后线程2开始在Core 3中执行,它尝试读取全局变量,并从主内存中读取它(因为它没有缓存的值),所以线程2正在读取一个过时的值。
我知道在C中,您可以使用volatile来强制compilier不读取值形式的CPU寄存器,这意味着易失变量将从缓存或主内存中获得其值。在我的上述场景中,即使我用volatile声明全局变量,最近的值仍将被缓存在L1缓存中,主内存仍然有一个旧的值,这个值将通过线程2读取。那么,我们如何解决这个问题呢?或者我的理解是错误的,使用volatile会使主内存中的变量直接更新,所以每次您尝试读取/写入一个易失性变量时,都会直接将它从/写到主存中吗?
发布于 2021-02-10 06:56:48
在某种程度上,人们注意到你问题的前提是有缺陷的,这是一个合理的答案。一般来说,这种情况很少发生,而且通常与种族状况没有区别。
然而,,是的,它可以发生。例如,请参阅记忆屏障,这是一个很好的例子,说明了这种情况(尽管是由于OOO的执行等等)。可能会发生。
尽管如此,为了确保您注意到的特定事件不会发生,您要寻找的是"缓存刷新“。在存在单独的数据和指令缓存的ARM/ARM 64处理器上,这一点确实很重要,但对于线程之间以这种方式传递的数据来说,这也是一个很好的习惯。您还可以签出执行类似任务的cache c编译器内置。希望其中之一能帮助你找到问题的根源。
但是,很可能您没有遇到缓存问题,并且更有可能出现争用状态。如果内存障碍/缓存刷新不能解决问题,请仔细检查代码的运行情况。
发布于 2021-02-10 07:03:30
如何确保C多线程程序读取主内存中的最新值?
您可能希望使用一些线程库,比如POSIX线程。阅读一些丝线教程,参见线程(7),使用创建(3)、初始化、锁定、线程条件变量等。
还可以阅读GNU libc和C编译器(例如,GCC,用作gcc -Wall -Wextra -g)和调试器(例如GDB)的文档。
准备好对抗海生虫。
一般来说,你不能静态地证明你的C程序没有种族条件。见赖斯定理。您可以使用Frama-C或Clang静态分析仪之类的工具,也可以编写自己的GCC插件,或者改进或扩展这草稿中描述的比斯蒙。
你可能会对CompCert感兴趣。
您不能确定您的程序从内存中读取“最新”值。
(除非添加了一些程序集代码)
阅读关于缓存一致性协议的文章。
https://stackoverflow.com/questions/66131775
复制相似问题