C原子操作,如果写操作都是原子交换,我需要原子负载吗?

C原子操作,如果写操作都是原子交换,我需要原子负载吗?,c,multithreading,atomic,thread-synchronization,compare-and-swap,C,Multithreading,Atomic,Thread Synchronization,Compare And Swap,我正在用C编写一个程序。为了简单起见,我们可以说:有几个变量,许多线程都可以读写。每次写入其中一个时,它都是通过原子交换(GCC原子操作、同步和交换)写入的。我是否需要在每次读取其中一个变量时使用原子负载,或者原子写入是否足以避免在写入过程中读取数据 注意,需要使用其中一个变量的数据的任何位置都会首先复制值: int success = 0; while ( !success ) { int x = shared_x; ... work with x, result in y ...

我正在用C编写一个程序。为了简单起见,我们可以说:有几个变量,许多线程都可以读写。每次写入其中一个时,它都是通过原子交换(GCC原子操作、同步和交换)写入的。我是否需要在每次读取其中一个变量时使用原子负载,或者原子写入是否足以避免在写入过程中读取数据

注意,需要使用其中一个变量的数据的任何位置都会首先复制值:

int success = 0;
while ( !success ) {
  int x = shared_x;
  ... work with x, result in y ...
  success = cmp_swap( &shared_x, x, y );
}

我的问题不是关于数据竞赛,也就是说我不担心我会丢失数据。我担心的是,在我阅读它的过程中,共享_x的价值可能会发生变化。假设它是一个8字节的整数,这是否是一个潜在的问题:假设shared_x是一个64位整数,8字节。我的x=shared_x是否可能复制前4个字节,然后某个东西自动写入shared_x,然后此语句完成读取第二个4个字节。这将导致x包含旧值shared_x的前4个字节,以及新shared_x的最后4个字节。我怀疑原子交换中的内存屏障(使用_sync_bool_compare_和_swap)足以防止这种情况发生。。。但我不确定。

看起来您正在阅读
共享的\ux
,计算新的内容,然后写回
共享的\ux
。您写入共享的值似乎取决于您最初从中读取的值

如果是这样的话,您就有一个依赖关系,并且很可能不仅需要使读取原子化,还需要使整个“读取、计算、写回”操作原子化。也就是说,您需要同步它。就像使用互斥锁一样

我之所以说“最有可能”,是因为我不能确定我是否不知道代码的实际功能。您需要分析在争用条件下发生的情况,即线程a写入
shared_x
,而线程B当前正在基于
shared_x
的旧值进行计算,然后将结果写回它。线程A写入的值将永远丢失。我不知道这对你来说是否有问题。只有你知道。如果争用条件正常,则不需要同步或使读取原子化

如果您只想确保从
shared_x
读取内容不会变成垃圾,并且不关心上述竞争条件,那么答案是“很可能您不需要使读取原子化”。您可以在此处阅读详细信息,而不是复制和粘贴

<>虽然问题是C++,C也一样。


请注意,原子现在也在C标准(C11)中,由
标题和
\u原子类型限定符提供。当然,还不是所有的编译器都支持C11。

更新了我的示例,现在它显示了在计算新值时,当其他程序写入时会发生什么,它只是重新开始并重试。@Exodist这里需要的透视图是整个程序,而不仅仅是其中的一部分。你需要自己做分析。假设一个竞争条件并遵循程序逻辑。如果比赛条件没有任何不良影响,你就没事了。你也可以手动介绍比赛情况并观察。我一定没有正确地问我的问题。我不关心工作的同步。我将更新上面的问题。更新后,我希望确保int x不会得到旧共享_x的一半值,也不会得到新共享_x的一半值。@Exodist OK。通过链接到问题的副本更新了答案。