对于某些技术的掌握,你必须知道它是如何在一个抽象级别下制作的。在多线程编程的情况下,了解同步原语会很好 这是一个问题,如何在.NET中实现Lock(Monitor)?
我对这些观点感兴趣:
- 它是否使用OS对象?;
- 是否需要用户模式或内核模式?
- 等待锁定的线程的开销是多少?
- 在什么情况下,可能会违反等待锁的线程队列?
更新
“如果多个线程争用锁定,它们就会在”就绪队列“中排队,并按照先到先得的原则授予锁定。注意:Windows和CLR行为的细微差别意味着有时可以违反队列的公平性。“[C#4.0 in a Nutshell,Joseph Albahari]所以这就是我在关于'违规队列'的最后一个问题中所要求的。
答案 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”这样的“诚实”算法,但并不能保证这一点。 (例如,如果来自“等待队列”的线程将被暂停,它将在恢复时移动到队列的末尾。)