Java:嵌套同步块



我在Heinz Kabutz的Java Expert通讯版本中看到了这一点,尽管Kabutz博士的其余(实际上是所有)文章都得到了很好的解释和详细,但他似乎掩盖了这段代码正在做什么,或者更重要的是,它的意义是什么:

public class SomeObject {
    private Object lock1;
    private Object lock2;
    public void doSomething() {
        synchronized(lock1) {
            synchronized(lock2) {
                // ...
            }
        }
    }
}

嵌套synchronized块有什么含义?这对尝试doSomething()的不同线程有何影响?

必须

注意 2 个可能的问题

  1. 如果嵌套锁使用等待/通知,则很容易导致死锁。 以下是原因的解释。https://jenkov.com/tutorials/java-concurrency/nested-monitor-lockout.html

  2. 应该警惕的是,如果另一个方法希望锁定相同的两个对象,它们必须始终以相同的顺序进行,否则可能会出现另一种死锁情况,如本文所述:如何避免嵌套同步和由此产生的死锁

就其本身而言,此代码片段不会引起任何问题。但是,如果有类似此代码的内容,问题可能会以死锁的形式出现;我们有两种同步块的方法,对象以相反的顺序锁定

-
public void doSomething() {
    synchronized(lock1) {
        synchronized(lock2) {
            // ...
        }
    }
}
public void doOtherthing() {
    synchronized(lock2) {
        synchronized(lock1) {
            // ...
        }
    } 
}

现在,如果多个线程尝试访问这些方法,则由于嵌套的同步块,可能会出现死锁。

根据嵌套监视器锁定教程

在嵌套监视器锁定中,线程 1 持有锁 A,并等待获取来自线程 2 的信号。线程 2 需要锁 A 来发送信号到线程 1。在死锁中,两个线程正在等待彼此释放锁。

僵局可能类似于两个人被囚禁在两个房间里,他们想切换到另一个房间,但他们都只有对方的钥匙。而嵌套监视器锁定就像老板被安排睡在房间里一样,假设他只有在有人进入房间时才会被唤醒。秘书负责叫醒他的老板。但老板睡觉时还拿着房间的钥匙,所以秘书不能进来叫醒他。

最新更新