将uint32写入uint64不是原子的。为什么?

时间:2019-05-07 06:50:42

标签: x86 atomic

在第410页的Is Parallel Programming Hard, And, If So,What Can You Do About It中写道:

  

快速测验5.17:

     

为什么清单5.4中的inc_count()不需要使用原子指令?

     

答案:
  (..)在以下情况下需要原子指令:   每个线程的计数器变量小于全局global_count   (..)

为简化起见,该句子适用于以下示例:

uint64 global_count = 0;

void f(){
    uint32 sum = sum_of_smaller_thread_locals(); # sum is a variable 
    WRITE_ONCE(global_count, sum);
}

我不明白为什么在这种情况下我们需要原子指令?

1 个答案:

答案 0 :(得分:1)

正如Peter Cordes指出的那样,每线程增量将需要原子指令。文字中给出了原因,但是多余的“但是”却使它有些模糊:

  

也就是说,在以下情况下需要原子指令   每个线程的计数器变量小于全局变量global_   计数。 但是,请注意,在32位系统上,每线程计数器   变量可能需要限制为32位才能求和   准确,但使用64位global_count变量以避免溢出。   在这种情况下,必须将每个线程的计数器变量清零   定期进行以避免溢出。   请注意,此调零不能延迟太久或溢出   较小的每线程变量将导致。因此,这种方法   对基础系统施加实时要求,进而   必须格外小心地使用。

     

相反,如果所有变量都是   大小相同,任何变量的溢出都是无害的,因为最终   总和将为单词大小的模数。

如果主线程清除每个线程的计数器,则需要通过原子交换来执行此操作,以避免可能的数据丢失。如果清除每个线程的增量,为避免数据丢失,它们将需要其他(可能更复杂)的互锁类型。