假设我有一个用作帧缓冲区的大内存缓冲区,它由一个线程(甚至多个线程,保证没有两个线程同时写入相同的字节)不断写入。这些写入在时间上是不确定的,分散在代码库中,并且无法被阻止。
我有另一个单线程定期读取(复制)整个缓冲区以生成显示帧。这个读取也不应该被阻止。就我而言,撕裂不是问题。换句话说,我唯一的目标是写入线程所做的每一个更改最终都应该出现在读取线程中。排序或一些(与显示刷新率相比可以忽略不计)延迟无关紧要。
同时读取和写入相同的内存位置是一种数据竞争,这会导致 c++11 中的未定义行为,本文列出了相同的非常可怕的示例,其中优化编译器生成的内存读取代码会改变数据竞争的存在。
不过,我需要一些解决方案,而无需完全重新设计此遗留代码。从实际的角度来看,每条建议都会考虑什么是安全的,而不管它在理论上是否正确。我也对非完全便携的解决方案持开放态度。
除此之外,我有一个数据竞争,我可以通过在线程之间建立同步关系(获取-释放一个原子保护变量,仅用于其他目的)或通过将特定于平台的内存栅栏调用添加到编写器线程中的关键点。
我针对数据竞赛的想法:
使用组件作为阅读线程。我会尽量避免这种情况。
使内存缓冲区易失,从而防止编译器优化参考文章中描述的这些讨厌的东西。
将读取线程的代码放在单独的编译单元中,用-O0编译
+1。保持一切原样,交叉手指(因为目前我没有注意到问题):)
上面列表中最安全的是什么?你看到更好的解决方案了吗?
仅供参考,目标平台是 ARM(多核)和 x86(用于测试)。
(这个问题将前一个问题具体化,这有点太笼统了。)