lock 语句使用啥类型的锁定机制
Posted
技术标签:
【中文标题】lock 语句使用啥类型的锁定机制【英文标题】:What type of locking mechanism does lock statement uselock 语句使用什么类型的锁定机制 【发布时间】:2012-07-06 12:08:08 【问题描述】:c# lock 关键字是否使用“yielding”、“spin-locking”或混合方法来处理争用?
到目前为止,我对 .net lock 语句的搜索还没有找到答案。 如果我找到更多,我会发布。 到目前为止,我能找到的只有When should one use a spinlock ...,Mecki 接受了措辞优美的回答。
但我正在寻找有关 .net/c# 的明确答案或文档(如果有人有的话)。
【问题讨论】:
【参考方案1】:以下代码:
lock (_syncRoot)
// Do stuff
被编译器翻译成:
Monitor.Enter(_syncRoot)
try
// Do stuff
finally
Monitor.Exit(_syncRoot);
这是幼稚(和旧)的实现,实际上在 .NET 4.0 中实现或多或少是这样的(完整参考请参阅Eric's blog):
bool locked = false;
try
Monitor.Enter(_syncRoot, ref locked);
finally
if (locked)
Monitor.Exit(_syncRoot);
已编辑
也就是说问题是Monitor.Enter()
是如何工作的?嗯,默认 Mono 实现使用信号量来获取锁,但 Microsoft .NET 实现的行为不同。
我正在阅读并发 Windows 编程(作者 Joe Duffy),当一个段落引起了我的注意时,我的第一个回答是“不,它不使用旋转,因为总体上性能可能不好案件”。正确答案是“是的,.NET Monitor
使用旋转”。 .NET Monitor
和 Windows 关键部分都会在回退到真正等待内核对象之前执行短暂的旋转。这种算法被称为“两阶段锁定协议”,它是合适的,因为上下文切换和内核转换非常广泛,在多处理器机器上旋转可以避免这两者。
此外,不要忘记这些是实现细节,并且可以在任何版本中更改(或者由于 JIT 编译器,不同硬件的算法可能不同)。
【讨论】:
【参考方案2】:lock (obj)
只是 Monitor.Enter 在尝试中的语法糖...终于。
Monitor.Enter(obj);
try
finally
Monitor.Exit(obj);
现在是 little better(感谢 Mark 和 Adriano 让我了解最新情况)。
bool locked = false;
try
Monitor.Enter(_syncRoot, ref locked);
finally
if (locked)
Monitor.Exit(_syncRoot);
【讨论】:
@MarcGravell 所以我刚刚注意到了。刚刚花了最后 10 分钟阅读 FAIC :)【参考方案3】:这是微软文档说 lock() 包装 Monitor.Enter/Exit
“使用 C# lock 语句,它将 Enter 和 Exit 方法包装在 try...finally 块中。”
来自http://msdn.microsoft.com/en-us/library/de0542zz.aspx
如果你想要一个自旋锁类型,你可以使用 ReaderWriterLockSlim()
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
【讨论】:
为什么不加评论就投反对票?我指向请求的文档并建议使用提到的自旋锁的替代方法。以上是关于lock 语句使用啥类型的锁定机制的主要内容,如果未能解决你的问题,请参考以下文章
如果 package-lock.json 锁定它,那么在 package.json 中声明“兼容版本”(^version)有啥意义?