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呼び出しはバランスをとることに注意してください。クリティカル領域をマークするための呼び出しは、SpinLockの取得中にスレッドの中断が損傷を与える可能性があることをCLRに通知するために必要です。詳細については、こちらをご覧ください。

于 2011-04-05T03:28:48.260 に答える