这段代码是线程安全的吗?

Rab*_*bit 3 c++ thread-safety lock-free

这是我正在维护的一些代码的简化版本:

int SomeFunc() 
{
  const long lIndex = m_lCurrentIndex;
  int nSum = 0;
  nSum += m_someArray[lIndex];
  nSum += m_someArray[lIndex];
  return nSum;
}
Run Code Online (Sandbox Code Playgroud)

lCurrentIndex由另一个线程定期更新.问题是; 将制作m_CurrentIndex的本地副本确保对m_someArray的两次访问都使用相同的索引?

请注意,这是一个简化的例子; 我正在考虑制作本地副本的概念,而不是这里显示的确切代码段.我知道编译器会将值放在寄存器中,但这仍然是本地副本,而不是从lCurrentIndex读取两次.

谢谢!

编辑:初始分配是安全的,在我们的设置中保证两者都是32位.Edit2:它们在32位边界上正确对齐(忘了那个)

小智 15

不,读取共享变量的本地的初始化不一定是原子的.(例如,考虑在8位平台上需要什么代码)通常,编写线程安全代码的唯一方法是使用编译器和/或OS指定的原子操作,或使用操作系统锁定功能.

  • 在32位平台上,`long` _may_是64位,特别是_need not_是原子的.后者意味着分配一个"long"值可以分几个步骤完成,而另一个线程可能会在这些步骤之间改变源值_所以你最终得到旧值的一半比特,以及新的一半比特.一.也就是说,在x86上,`long`传统上是32位和原子. (4认同)
  • 不,我说它可能在初始化后立即具有不确定的价值(因为线程问题). (3认同)
  • @Neil我明白了.我专注于"一旦初始化,lIndex在整个函数的执行路径中保持不变",并且你专注于"lIndex的初始值可能是不确定的,因此不能假设操作someArray [lIndex]是有意义的甚至是合法的" . (2认同)

Dan*_*nas 6

将制作m_CurrentIndex的本地副本确保对m_someArray的两次访问都使用相同的索引?

在同一个执行中SomeFunc,当然是.局部整数变量(lIndex)不会在函数中间神奇地改变它的值.

当然,以下情况也是如此:(m_someArray[lIndex]与之相反lIndex)的实际价值可能会发生变化; m_ someArray本身可能会改变; 以及尼尔所说的lIndex初始值的有效性.