在.NET中锁定(监视)内部实现

ale*_*ber 33 .net c# multithreading synchronization monitor

掌握某些技术时,你必须知道它是如何在一个抽象级别下制作的.在多线程编程的情况下,了解同步原语将是很好的.
这是一个问题,如何在.NET中实现Lock(Monitor)?

我对以下几点感兴趣:
- 它是否使用OS对象?
- 是否需要用户模式或内核模式?
- 等待锁定的线程的开销是多少?
- 在什么情况下,等待锁的线程队列可能会被违反?

更新:
"如果有多个线程争用锁定,它们会在"就绪队列"上排队,并按照先到先得的原则授予锁定.注意:Windows和CLR行为的细微差别意味着有时会违反队列的公平性. "[C#4.0 in a Nutshell,Joseph Albahari]所以这就是我在关于'违规队列'的最后一个问题中所要求的.

Ste*_*ary 19

维基百科的文章有一个什么样的"监视器"是一个相当不错的描述,以及作为其基础的技术,条件变量.

请注意,.NET Monitor是条件变量的正确实现; 大多数已发布的CV的Win32实现都是不正确的,即使是在Dobbs博士等通常有信誉的来源中也是如此.这是因为无法从现有的Win32同步原语轻松构建 CV .

.NET CV实现不仅仅是在Win32原语上构建一个浅(且不正确)的包装器,而是利用它在.NET平台上实现自己的等待队列等事实.

  • 使用.NET 4.0,它更加正确.如果在<< Monitor.Enter`之后出现异常,则有可能锁定"卡住"(请参阅​​此http://stackoverflow.com/questions/2837070/lock-statement-vs-monitor-enter-方法/ 2837224#2837224) (5认同)
  • 如果您想在Win32中使用条件变量,请使用Windows V6(Vista/2008)中引入的操作系统实现:http://msdn.microsoft.com/en-gb/library/ms682052(VS.85).aspx (3认同)
  • 你的维基百科链接没有回答任何问题,问题最重要的部分是内核与用户模式......那篇文章是另一个聪明的聪明点 (2认同)

ale*_*ber 18

经过一些调查后,我找到了问题的答案.一般来说,CodeInChaos和Henk Holterman是对的,但这里有一些细节.

当线程开始首先争用与其他线程的锁定时,它会尝试旋转等待循环一段时间以获取锁定.所有这些操作都在用户模式下执行.然后,如果OS内核对象没有成功Event创建,则线程切换到内核模式并等待来自此的信号Event.

所以回答我的问题是:
1.更好的情况下没有,但更糟糕的是(Event对象懒惰地创建,如果需要);
2.一般情况下,它在用户模式下工作,但如果线程争用锁的时间过长,则可以将线程切换到内核模式(通过Win API非托管函数调用);
3.从用户模式切换到内核模式的开销(~1000个CPU周期);
微软声称它是像"FIFO"这样的"诚实"算法,但并不能保证这一点.(例如,如果来自"等待队列"的线程将被暂停,它将在恢复时移动到队列的末尾.)

  • 你能发布研究资料吗?这会有所帮助 (10认同)
  • 这在 Clr Via C# 中进行了详细讨论,Jeffrey Richter 将其称为“混合锁”。在用户模式下,监视器旋转并与其他线程竞争(因为它们没有被阻塞),一旦它们被提升为内核模式锁,它们就会被阻塞,从而释放周期。 (3认同)
  • 我想看看1和2语句的详细解释。我想知道 .NET 何时决定在 Monitor 实现中进入内核模式 (2认同)