Concurrency 你能解释一下锁的订购吗?

Concurrency 你能解释一下锁的订购吗?,concurrency,locking,deadlock,Concurrency,Locking,Deadlock,我学会了,我应该解锁反向顺序来锁定顺序。 比如说 A.lock(); B.lock(); B.unlock(); A.unlock(); 但是,如果我这样做会怎么样: A.lock(); B.lock(); A.unlock(); B.unlock(); 我试着制造一个死锁场景, 但如果我总是先锁定A,然后锁定B,那么我不知道死锁会如何发生。 您能帮我一下吗?锁顺序只是指通过按固定顺序获取锁来防止死锁,并且在开始解锁后不再获取锁 我不认为解锁的顺序在这里有任何区别(事实上,尽快释放一个锁应该

我学会了,我应该解锁反向顺序来锁定顺序。 比如说

A.lock();
B.lock();
B.unlock();
A.unlock();
但是,如果我这样做会怎么样:

A.lock();
B.lock();
A.unlock();
B.unlock();
我试着制造一个死锁场景, 但如果我总是先锁定A,然后锁定B,那么我不知道死锁会如何发生。
您能帮我一下吗?

锁顺序只是指通过按固定顺序获取锁来防止死锁,并且在开始解锁后不再获取锁


我不认为解锁的顺序在这里有任何区别(事实上,尽快释放一个锁应该是有益的,即使它不正常)

您的示例永远不会死锁。按相反顺序解锁并不重要,而是按一致的顺序锁定。这将导致死锁,即使解锁顺序相反

Thread 1

A.lock();
B.lock();
B.unlock();
A.unlock();

Thread 2

B.lock();
A.lock();
A.unlock();
B.unlock();

我认为这里不会出现僵局。一般的死锁概念是一个线程等待另一个线程锁定的资源,而另一个线程需要第一个线程锁定的资源来完成并释放第一个线程所需的资源


解锁顺序不会影响系统死锁的可能性,但是有一个原因需要考虑解锁顺序:


为了避免死锁,您必须确保您的锁定/解锁配对,这样您就不会错过解锁。作为一种风格方法,通过显著地拥有负责特定锁的代码块,可以更容易地直观地识别锁和解锁是成对的。最终的效果是,明确正确的代码可能会像您所描述的那样获取并释放锁。

在给出的简单示例中,不需要按相反顺序解锁以避免死锁

但是随着代码变得更加复杂,按相反顺序解锁有助于保持正确的锁顺序

考虑:

A.lock();
B.lock();
Foo();
A.unlock();
Bar();
B.unlock();
如果
Bar()。你拿着B,然后试图得到A。现在它可以死锁了

如果以反向顺序样式解锁(如果使用RAII,这非常自然):


如果
Bar()
尝试获取锁,则这无关紧要,因为锁的顺序将被保留。

对于Java,如果
已同步
关键字用于锁定。对于使用
synchronized
关键字,无法以不同的顺序解锁

synchronized(a) {
  synchronized(b) {
    // statements
  }
}

他们的回答很好,这里是另一种情况,如果执行无序的锁定和释放,可能会发生死锁。一个词,无序释放和锁定打破了我们用来设计共享资源管理和关键区域的假设。

您是说有多个进程持有锁定还是您只处理一个进程?当然是多个进程。不是“当然”,为什么是多个进程?同样适用于单个进程中的线程。在我看来,这是正确的答案:如果您接受在整个系统的不同级别(内部函数等)上以相同的顺序获取锁的规则,并且不以相反的顺序释放锁,那么Adrian答案中的场景可能会导致死锁。我希望这个“can deadlock”在“good style”的论点(我也完全同意)下面更明显一点。这不仅是正确的答案,它还指出所有声称解锁顺序与死锁无关的答案都是错误的。好吧,这个问题只会在重新获取以前释放的锁时发生(没有先释放“以后”的锁)。我假定错误的答案将锁顺序定义为“以固定顺序获得锁,并且在开始解锁后不再获得锁”。引用总是雄辩的Linus Torvalds的话:“事实是,解锁不需要干净地嵌套。这是一个坚如磐石的事实。锁定顺序很重要,解锁顺序不重要。如果你不能接受这一事实,然后你会说“解锁顺序应该很重要,只是为了保持事物的整洁”,然后当你不能按解锁顺序解锁时,你会被拧紧和/或困惑。有许多完全正确的理由不按相反顺序解锁。"我没有声称其他人的答案是错误的,也没有说你必须以相反的顺序解锁。我指出,以相反的顺序解锁可以更容易地确保始终保持锁定顺序,即使你的代码不断发展。我想表示,我不同意对这个答案的否决票。尽管这不是mo在阐述这个问题时,它确实显示了另一种观点,也许有助于理解这个问题
synchronized(a) {
  synchronized(b) {
    // statements
  }
}
      > lock(B)                                                                                                                                                                                                 
      >  ----------    lock(C)
      >  ----------    lock(B)    >>>> would block here 
      >  ----------    release(B)
      >  ----------    release(C)
      > lock(C)       >>>>>> would block here 
      > release(B)
      > release(C)