在我阅读ReaderWriterLockSlim
锁定机制时,There was this guy建议Interlock
函数可用于更精细的锁定
另外,我发现了来自Marc的另一个答案here:
...写入对克隆的副本进行更改,然后使用 Interlocked.CompareExchange交换引用(重新应用它们的 如果另一个线程在临时中突变了引用,则更改。
好吧,目前我对Interlocked
对象的了解是,它(在多线程环境中)用于执行原子additions
,compare
,compareExchange
操作。 (我知道如何使用它)
但是(,这是我的问题) -
问题
如何将其用作锁? (示例代码将非常感谢)
为简单起见,我粘贴了这段代码(不是线程安全的 - 如果同时由两个线程调用Go
,则可能会得到一个被零除错误):
class ThreadUnsafe
{
static int _val1 = 1, _val2 = 1;
static void Go()
{
if (_val2 != 0) Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
}
如何使用Interlock替换锁(这可以解决问题)?
答案 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;
}