如果我不关心读取器是否会读取过时的数据,我是否需要写入器/读取器同步?



让我有一个阅读器线程。阅读器有一个bools矢量。矢量的大小不会改变,并且总是已知的。读取器从另一个源读取一些数据,根据数据计算索引,并检查vector[index]==true。如果为true,Reader将进一步发送数据。如果没有,则删除数据。让我有一个作家线程。Writer使vector[index]为true或false。如果我不担心会发送一些额外的数据块或丢失一些块,我真的需要向量的互斥体吗?以这种方式使用矢量绝对安全吗?

在没有同步的情况下从多个线程读取和写入相同的值,无论多么小,都是一种数据竞赛,是一种未定义行为。

即使硬件保证了高速缓存的一致性(如x86(,C++内存模型也被定义为在没有同步的情况下,每个线程都被假设为独立执行。然后,根据"好像"规则,允许编译器以其认为合适的任何方式优化和重新排序内存访问,因此具有数据竞争的程序的行为变得不可预测。阅读器线程可能永远不会";参见";任何更新的值。或者,在线程完成之前,编写器可能不会向内存中写入任何内容,或者以不同的顺序写入。行为可能在编译器版本、优化级别等之间发生变化。

请注意,同步并不意味着互斥,atomic也可以(原子向量有点复杂,但也是可能的,尽管我觉得用户空间互斥会更高效(。


额外注意:从多个线程访问同一向量时,不要忘记错误共享。

正如rustyx已经指出的,原子学可以做到这一点。

如果您只关心在未来的某个时刻读取值,而不受数据竞争的影响(因此写入和读取之间缺少先发生后发生的关系(,那么使用memory_order_release设置标志并使用memory_oorder_acquire获取标志就足够了。

在X86上;使用TSO存储器模型的所有常规存储器都是释放存储器并且所有常规负载都是获取负载。因此,在硬件层面上是没有代价的。只有编译器才会被阻止执行某些重新排序。

X86上代价高昂的写入是memory_order_sec_cst。在这种情况下,存储被放在存储缓冲区上,CPU停止执行任何加载,直到存储缓冲区耗尽。使用memory_order_sec_cst,存储被放置在存储缓冲区上,CPU可以继续执行下一条指令(甚至加载(;因此CPU不会停滞。

最新更新