1

给定以下代码:

...
private static SpinLock logLock = new SpinLock(false);
...

private static void ThreadFunc()
{
    bool lockTaken = false;
    logLock.Enter(ref lockTaken)
    {
        try
        {
            // do stuff with during an acquired SpinLock
        }
        finally
        {
            logLock.Exit();
        }
    }
}

如果 Enter 块“失败”,因为它在获取锁时收到 false,那么当前线程是否像自旋锁一样旋转并等到它可以获取它,或者这个块只是被绕过并且该线程丢失了?

谢谢,

斯科特

4

2 回答 2

2

根据定义,自旋锁会导致线程在等待获取锁而不是阻塞时自旋。如果无法获取锁,Enter 不会“失败”,它只是等待。

Enter 可能无法抛出异常的唯一情况是当线程所有权被激活时,使用 new SpinLock() 或 new SpinLock(true)。在这种情况下,当线程试图获取它已经拥有的锁时,会引发异常。在您的情况下,这永远不会发生,因为您创建了禁用跟踪的锁 (SpinLock(false))。如果线程试图重新获得锁,它只会死锁。

SpinLock.Enter方法的文档中对此进行了描述。

于 2010-07-05T10:59:13.950 回答
1

SpinLock基本上只是一个尝试将变量设置为特定值的循环

你可以考虑它的实现如下:

public struct SpinLock
{
    private volatile bool _Locked;

    public void Acquire()
    {
        while (_Locked)
            ;
        _Locked = true;
    }

    public void Release()
    {
        _Locked = false;
    }
}

(当然,上面的代码不是线程安全的,而且我知道这不是类方法的签名,它只是一个伪代码变体来显示它在做什么)

所以是的,如果 SpinLock 已经处于锁定状态,尝试获取它会一直旋转,直到它变得可用。

另外,请注意,默认情况下(如您的示例中),该结构不会跟踪谁拥有锁。这意味着如果一个线程尝试两次获取锁,它将在第二次尝试时与自己死锁。

SpinLock 的目的是成为一个开销很小的用户级锁。它不增加 GC 压力,也不分配任何内核同步对象,它只是一个带有几个字段的 struct。

于 2010-07-05T11:06:10.110 回答