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

时间:2011-02-24 23:18:37

标签: c# .net multithreading synchronization monitor

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

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

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

2 个答案:

答案 0 :(得分:19)

Wikipedia article可以很好地描述“监视器”是什么,以及它的基础技术,条件变量。

请注意,.NET Monitor是条件变量的正确实现;大多数已发布的CV的Win32实现都是不正确的,即使是在Dobbs博士等通常有信誉的来源中也是如此。这是因为简历cannot easily be built from the existing Win32 synchronization primitives

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

答案 1 :(得分:17)

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

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

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