我有一些代码必须是线程安全的,其行为类似于以下情况:


protected long m_RunningValue
protected long m_RunningCounter
protected object m_Lock = new object();

public long RunningValue { get { return Interlocked.Read(m_RunningValue); } }
public long RunningCounter { get { return Interlocked.Read(m_RunningCounter); } }

public void DoCalculation(int newValue, int newQuantity)
{
   lock(m_Lock)
   {
       Interlocked.Add(ref m_RunningValueA, newValue);
       Interlocked.Add(ref m_RunningCounter, newQuantity);
       if(Interlocked.Read(ref newQuantity) == 0)
       { 
         ...m_RunningValue gets further modified here
       }
   }
}

计算必须锁定值和计数器或竞赛条件可能会影响(...)块,但是在读出时,它们根本不需要同步,即,如果计数器和价值在尝试之间的价值变化,则阅读两者,这对我来说是100%。

读取上的互锁是在那里进行64位值的线程安全读数。

  1. 混合互锁和像这样的锁吗?我已经在其他网页上阅读了混合它们是不安全的,但是我找不到澄清,如果这意味着将它们混合是引入微妙的错误的好方法,或者如果在系统级别上,则可能会损坏所涉及的数据结构。

  2. 所有这些互锁(64位.NET 4.0运行时)的成本是否完全击败了保存properting()方法周围读者作者锁定的目的?

有帮助吗?

解决方案

关于编辑版本,这是 不是 保证是线程安全。

考虑一个32位平台。这意味着必须在两个单独的操作中访问64位长值。

一个线程很有可能读取数字的前半部分,然后换掉CPU,后半部分在后面后面变化。现在,该线程具有完全无效的值。

文档 互锁。阅读 明确提及:

读取方法和64位超载的增量,减少和添加方法仅在System.Intptr长64位的系统上才真正原子。在其他系统上,这些方法相对于彼此而言是原子的,但与访问数据的其他手段相对。因此,要在32位系统上安全的线程, 任何访问 必须通过联锁班级的成员进行64位值。

(强调我的)

编辑:现在已经对其进行了编辑,看起来有些愚蠢,但是我将其留在这里,以指出,如果您在某些地方互锁而不是其他地方,那就毫无意义。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top