使用.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的调用会产生任何问题吗?
答案 0 :(得分:1)
请注意,如果实际执行锁定,则开始/结束调用执行平衡,然后通过调用Exit()释放。标记关键区域的调用对于让CLR知道在获取SpinLock时线程中断可能是有害的是必要的。有关详细信息,请参阅here。