C#互锁功能作为锁机制?

时间:2014-05-24 08:31:31

标签: c# multithreading locking interlocked

在我阅读ReaderWriterLockSlim锁定机制时,There was this guy建议Interlock函数可用于更精细的锁定

另外,我发现了来自Marc的另一个答案here

  

...写入对克隆的副本进行更改,然后使用   Interlocked.CompareExchange交换引用(重新应用它们的   如果另一个线程在临时中突变了引用,则更改。

好吧,目前我对Interlocked对象的了解是,它(在多线程环境中)用于执行原子additionscomparecompareExchange操作。 (我知道如何使用它)

但是(,这是我的问题) -

问题

如何将其用作? (示例代码将非常感谢)

修改

为简单起见,我粘贴了这段代码(不是线程安全的 - 如果同时由两个线程调用Go,则可能会得到一个被零除错误):

class ThreadUnsafe
 {
   static int _val1 = 1, _val2 = 1;

   static void Go()
       {
        if (_val2 != 0) Console.WriteLine (_val1 / _val2);
        _val2 = 0;
       }
}

如何使用Interlock替换锁(这可以解决问题)?

2 个答案:

答案 0 :(得分:5)

Interlocked用于实现无锁算法和数据结构。因此,它不是“更精细的锁定”,甚至根本不是锁定。它允许您在多线程环境中安全地执行小型且定义良好的操作:例如,如果您希望两个线程增加相同的变量,则可以使用Interlocked来执行而不是获取重量级锁并使用“常规增量”。

但是,在常规锁定下,您可以使用Interlocked做很多很多事情。例如,任何涉及以原子方式修改多个变量的内容通常无法使用Interlocked完成,因此您无法将其用于示例。

但是,

Interlocked可以帮助开发人员实现锁定机制,尽管你也可以使用内置的机制。大多数锁需要内核支持才能中断被阻塞的线程,直到锁变为可用。因此,单独使用Interlocked可以实现的唯一一种锁是自旋锁:线程不断尝试获取的锁直到它工作。

class InterlockedLock
{
    private int locked;

    public void Lock()
    {
        while (Interlocked.CompareExchange(ref locked, 1, 0) != 0)
            continue; // spin
    }

    public void Unlock()
    {
        locked = 0;
    }
}

在此示例中,locked最初为零。当一个线程第一次尝试获取它时,locked变为1,后续线程尝试Lock它会旋转,直到有人调用Unlock再次使locked 0

答案 1 :(得分:0)

仅在旧值未更改时,使用旧值替换新值,即可锁定Interlocked。如果它有,我们再试一次,直到它没有(旋转)。

这可用于替换只更新单个值或实现SpinLock等轻量级锁定机制的细粒度锁。

示例

private int _value;

int oldValue;
int originalValue;
do
{
    oldValue = _value;
    originalValue = Interlocked.CompareExchange(ref _value, newValue, oldValue);
}
while (originalValue != oldValue);

而不是

lock(_lock)
{
    _value = newValue;
}