3

我有一个类型的共享变量double。这个变量将被两个线程访问。一个线程永远只会写入变量,而另一个线程永远只会读取变量。

我仍然在这里获得比赛条件吗?如果是,在 C++ 中是否有一种“简单”的方式来实现原子访问?如果读取比写入多得多,我如何有效地实现它?我需要将变量标记为volatile吗?

编辑:好的,“阅读器”线程定期处理批量数据,并且新值的传播不是时间敏感的。与其实现我没有好方法测试的复杂联锁,我可以只声明编写器线程将写入的另一个临时变量。然后,当阅读器完成一批时,它可以将临时值自动传播到实际变量。那将是无竞争条件的吗?

4

2 回答 2

8

是的,存在竞争条件,因为double变量在大多数处理器上都不是原子的。

使用 3 个双打(可能是一个中间有额外填充的数组,以避免错误共享导致性能下降)。

一份归读者所有,一份归作者所有,一份正在移交。

写入:写入写入槽,然后原子地交换(例如用InterlockedExchange)写入槽的指针/索引与切换槽的索引。由于索引是指针大小或更小,只要变量正确对齐,原子交换就很容易。如果您的平台偶然提供了带或不带内存屏障的互锁交换,请使用 with。

读取:以原子方式将读取槽的指针/索引与切换变量的索引交换。然后读取读取槽。

您实际上还应该包含一个版本号,因为读取线程往往会在最新和上一个插槽之间反弹。阅读时,在交换之前和之后都阅读,然后与更高版本一起使用。

或者,在 C++11 中,只需使用std::atomic.

警告:以上仅适用于单个作者/单个读者(此问题中的特殊情况)。如果您有多个,请考虑使用读写器锁或类似的锁来保护对变量的所有访问。

于 2012-04-17T22:35:01.163 回答
0

您可能想看看讨论原始类型的读/写的this:

C++ 对 int 的读写是原子的吗?

于 2012-04-17T22:35:22.943 回答