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