1

使用 .NET 反射器,我发现SpinLock结构在很多情况下调用Thread.BeginCriticalRegion而不调用Thread.EndCriticalRegion。例如,在公共函数 SpinLock.Enter(ref bool lockTaken) (.NET 4.0) 中:

// ...
Thread.BeginCriticalRegion();
if (Interlocked.CompareExchange(ref this.m_owner, managedThreadId, owner, ref lockTaken) == owner)
    return;  // <--- !!
Thread.EndCriticalRegion();
// ...

在另一种情况下, SpinLock.Exit 似乎在没有调用Thread.BeginCriticalRegion的情况下调用了 Thread.EndCriticalRegion

public void Exit(bool useMemoryBarrier)
{
    if (this.IsThreadOwnerTrackingEnabled && !this.IsHeldByCurrentThread)
        throw ...

    if (useMemoryBarrier)
    {
        if (this.IsThreadOwnerTrackingEnabled)
            Interlocked.Exchange(ref this.m_owner, 0);
        else
            Interlocked.Decrement(ref this.m_owner);
    }
    else if (this.IsThreadOwnerTrackingEnabled)
        this.m_owner = 0;
    else
    {
        int owner = this.m_owner;
        this.m_owner = owner - 1;
    }
    Thread.EndCriticalRegion();   // <--- ??
}

所以问题是:不平衡对 Begin/EndCriticalRegion 的调用是否会出现任何问题?

4

1 回答 1

1

请注意,如果锁实际被占用,然后通过调用 Exit() 释放,则 Begin/End 调用会进行平衡。标记关键区域的调用对于让 CLR 知道在获取 SpinLock 时线程中断可能会造成破坏是必要的。请参阅此处了解更多信息。

于 2011-04-05T03:28:48.260 回答