为什么嵌套锁不会导致死锁?
可能重复:
C#中的重入锁
为什么这个代码不会导致死锁?
private static readonly object a = new object();
…
lock(a) { lock(a) { .... } }
如果一个线程已经拥有一个锁,那么它可以“再次获得该锁”而没有问题。
至于这是为什么 ,(为什么这是一个好主意),考虑下面的情况,我们有一个定义的locking顺序在其他程序中 – > b:
void f() { lock(a) { /* do stuff inside a */ } } void doStuff() { lock(b) { //do stuff inside b, that involves leaving b in an inconsistent state f(); //do more stuff inside b so that its consistent again } }
哎呀,我们刚刚违反了我们的locking顺序,并在我们手中有潜在的僵局。
我们真的需要能够做到以下几点:
function doStuff() { lock(a) lock(b) { //do stuff inside b, that involves leaving b in an inconsistent state f(); //do more stuff inside b so that its consistent again } }
这样我们的locking顺序就被维护了,当我们调用f()
时候没有自我死锁。
lock
关键字使用重入锁,这意味着当前线程已经拥有该锁,所以它不会尝试重新获取它。
如果发生死锁
线程1获取lockingA
线程2获取lockingB
线程1尝试获取锁B(等待线程2完成)线程2尝试获取锁A(等待线程1完成)
两个线程现在正在彼此等待,从而陷入僵局。
从C#语言规范的第8.12节 :
在保持互斥锁的同时,在同一个执行线程中执行的代码也可以获得并释放该锁。 但是,在locking被释放之前,在其他线程中执行的代码被阻止获取locking。
内部的lock
范围应该与外部在同一个线程中。