我了解到应该先解锁逆序,然后才能锁定顺序。例如:
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,那么我不知道死锁会发生在哪里。你能帮我吗?
A.lock();
B.lock();
Foo();
A.unlock();
Bar();
B.unlock();
如果Bar()
试图重新获取 A,那么你已经打破了锁的顺序。你持有 B 并尝试获取 A。此时可能会发生死锁。A.lock();
B.lock();
Foo();
B.unlock();
Bar();
A.unlock();
那么如果 Bar()
试图获取锁,锁定顺序将得以保留,这时就无所谓了。
锁定顺序仅意味着您按照固定顺序获取锁,并在开始解锁后不再获取锁,以防止死锁。
我认为在这里解锁的顺序并不重要(事实上,尽早释放锁甚至是无序的应该是有益的)。
你的示例永远不会发生死锁。按相反的顺序解锁并不重要,重要的是以一致的顺序进行锁定。即使解锁是按相反的顺序进行的,这也会导致死锁。
Thread 1
A.lock();
B.lock();
B.unlock();
A.unlock();
Thread 2
B.lock();
A.lock();
A.unlock();
B.unlock();
> lock(B)
> ---------- lock(C)
> ---------- lock(B) >>>> would block here
> ---------- release(B)
> ---------- release(C)
> lock(C) >>>>>> would block here
> release(B)
> release(C)
他们的答复非常棒,下面是另一种情况:如果执行无序的锁定和释放,死锁可能会发生。简言之,无序的释放和锁定 打破了我们用来设计共享资源管理和关键区域的假设。
synchronized
关键字进行锁定,则解锁的顺序是相反的。使用synchronized
关键字进行锁定后,无法以不同的顺序进行解锁。synchronized(a) {
synchronized(b) {
// statements
}
}