下面的代码会导致在.NET 上使用 C # 时出现死锁吗?
class MyClass { private object lockObj = new object(); public void Foo() { lock(lockObj) { Bar(); } } public void Bar() { lock(lockObj) { // Do something } } }
不,只要你锁定的是同一个对象就行。递归代码有效地 已经有锁了,因此可以不受阻碍地继续。
lock(object) {...}是使用 监视器类的简写。作为 马克指出,Monitor允许 Reentrant _ (子程序) rel = “ noReferrer”> re-entrancy ,所以反复尝试锁定对象 当前线程已经在其上有一个锁将工作得很好。
lock(object) {...}
Monitor
如果你开始锁定 与众不同对象,那就是你必须小心的时候了。特别要注意:
如果您打破了这些规则中的任何一条,那么几乎可以肯定会出现死锁问题 在某个时候。
这里有一个很好的网页描述线程同步在.NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
另外,一次锁定尽可能少的对象。考虑在可能的情况下应用 粗粒度锁。这个想法是,如果你可以编写你的代码,有一个对象图,你可以获得锁的根对象图,然后这样做。这意味着您对根对象拥有一个锁,因此不必太担心获取/释放锁的顺序。
(进一步注意,您的示例在技术上不是递归的。为了使其具有递归性,Bar()必须调用自身,通常作为迭代的一部分。)
Bar()
好吧,Monitor允许重入,所以你不能死锁自己... 所以,不: 它不应该这样做
如果一个线程已经持有一个锁,那么它将不会阻塞自己。那个。Net 框架确保了这一点。您只需要确保两个线程不会尝试通过任何代码路径获取相同的两个顺序不一致的锁。
同一个线程可以多次获取相同的锁,但是您必须确保释放锁的次数与获取锁的次数相同。当然,只要您使用“ lock”关键字来完成这个任务,就会自动完成。
不,这个代码不会有死锁。 如果您真的想创建死锁,最简单的一个需要至少2个资源。 考虑一下狗和骨头的场景。 一只狗对一块骨头有完全的控制权,所以其他的狗只能等待。 2.两只狗有两块骨头,当它们锁定自己的骨头并寻找其他骨头时,至少需要制造一个僵局。
等等,狗和骨头造成了更复杂的僵局。