为什么这段代码不会造成死锁?
private static readonly object a = new object();
...
lock(a)
{
lock(a)
{
....
}
}
答案 0 :(得分:42)
如果一个线程已经拥有一个锁,那么它可以再次“取消锁定”。
至于为什么,(以及为什么这是一个好主意),请考虑以下情况,其中我们在 - >程序的其他地方有一个已定义的锁定顺序。 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
}
}
糟糕,我们只是违反了我们的锁定顺序,并且可能会陷入僵局。
我们确实需要能够执行以下操作:
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
}
}
因此,当我们调用f()
时,我们的锁定顺序会保持不会发生自我死锁。
答案 1 :(得分:18)
lock
关键字使用可重入锁定,这意味着当前线程已经锁定,因此它不会尝试重新获取它。
如果
,就会发生死锁线程1获取锁定A
线程2获取锁B
线程1尝试获取锁B(等待线程2完成)
线程2尝试获取锁A(等待线程1完成)
两个线程现在都在等待,因此陷入僵局。
答案 2 :(得分:8)
来自C#语言规范的section 8.12:
虽然举行互斥锁定, 代码在同一执行中执行 线程也可以获取和释放 锁。但是,代码在其他代码中执行 线程被阻止获取 锁定直到锁定被释放。
很明显,内部lock
范围与外部{{p}>在同一个线程中。