.NET SpinLock 未释放 Thread.BeginCriticalSection
使用.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.EndCriticalRegion,而没有调用 Thread.BeginCriticalRegion 。
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 的调用是否会产生任何问题?
Using .NET reflector, I find that the SpinLock structure has a lot of cases where it calls Thread.BeginCriticalRegion and doesn't call Thread.EndCriticalRegion.
For example, in the public function 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();
// ...
In another case, SpinLock.Exit seems to call Thread.EndCriticalRegion without having called Thread.BeginCriticalRegion.
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(); // <--- ??
}
So the question: do any problems ensue from not balancing calls to Begin/EndCriticalRegion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请注意,如果实际获取了锁,然后通过调用 Exit() 释放锁,则 Begin/End 会调用 do 平衡。标记关键区域的调用对于让 CLR 知道在获取 SpinLock 时线程中断可能会造成破坏是必要的。有关详细信息,请参阅此处。
Note that the Begin/End calls do balance if the lock is actually taken and then released by calling Exit(). The calls to mark the critical region are necessary to let the CLR know that thread interruptions may be damaging while a SpinLock is acquired. See here for more info.