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 语句使用啥类型的锁定机制的主要内容,如果未能解决你的问题,请参考以下文章

镜头上的lock是啥意思

python-锁机制

如果 package-lock.json 锁定它,那么在 package.json 中声明“兼容版本”(^version)有啥意义?

MySQL的SQL语句事务性语句和锁定语句LOCK INSTANCEFORBACKUP 等语句

C#锁定基于类属性

我啥时候必须重新锁定相机?