【问题标题】:C# Interlocked functions as a lock mechanism?C# Interlocked 用作锁定机制?
【发布时间】:2014-07-13 14:56:16
【问题描述】:

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

另外,我发现here Marc 的另一个答案:

...写入对克隆副本进行更改,然后使用 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 来更换锁(这可以解决问题)?

【问题讨论】:

  • 如何将其用作锁? - 使用lock(){}

标签: c# multithreading locking interlocked


【解决方案1】:

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。

【讨论】:

  • 您希望volatile 确保对locked 的写入不会进一步重新排序,直到在关键部分中的任何写入之前结束。
【解决方案2】:

使用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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    相关资源
    最近更新 更多