混合锁和联锁操作是否安全?

时间:2010-12-07 23:28:02

标签: c# thread-safety interlocked readerwriterlockslim

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


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
       }
   }
}

计算必须锁定值和计数器,否则竞争条件可能会影响if(...)块,但是在读出时根本不需要同步,即计数器和值是否更改尝试阅读两者之间,这对我来说是100%的确定。

读取时的互锁用于读取64位值的线程安全性。

  1. 这样的混合联锁和锁是否安全?我在其他网页上看到混合它们是不安全的,但是如果这意味着混合它们是引入细微错误的好方法,或者如果在系统级别这会破坏所涉及的数据结构,我无法找到澄清。 / p>

  2. 所有这些互锁(64位.NET 4.0运行时)的成本是否完全违背了在属性get()方法周围保存ReaderWriterSlim锁的目的?

1 个答案:

答案 0 :(得分:5)

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

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

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

Interlocked.Read的文档明确提到:

  

只有在System.IntPtr为64位长的系统上,Read方法和Increment,Decrement和Add方法的64位重载才是真正原子的。在其他系统上,这些方法相互之间是原子的,但与其他访问数据的方法无关。因此,要在32位系统上保持线程安全,任何访问到64位值必须通过Interlocked类的成员进行。

(强调我的)

编辑:现在它已被编辑回来看起来有点傻了,但是我会留在这里指出,如果你在某些地方互锁而不是其他地方,这是毫无意义的。

相关问题