6

根据我的理解,下面这段代码应该会导致死锁。原因是,当线程 t1 锁定静态对象 firstData 时,他已经获得了对该类的锁定。所以,当他试图锁定另一个静态对象 secondData 时,请求应该被阻塞。

但是,程序运行良好并打印*** Successfully acquired both the locks

锁定我在这里丢失的静态对象是什么?

public class Deadlock {
    public static void main(String[] args) {

        Thread t1 = new Thread(new DeadlockRunnable());
        t1.start();
    }
} 

 class DeadlockRunnable implements Runnable {
    static  Object firstData = new Object();
    static  Object secondData = new Object();

    public void run() {
        synchronized(firstData) {
            synchronized(secondData) {
                System.out.println("*** Successfully acquired both the locks");
            }
        }
    }

}

对于所有回答锁在对象而不是类上的人,请看看这个

4

2 回答 2

14

首先,你这里有一个错误:

原因是,当线程 t1 锁定静态对象 firstData 时,他已经获得了对该类的锁定。

锁定静态对象仅锁定该对象,而不锁定类。您正在锁定两个单独的对象。

您提到的问题是关于同步方法而不是同步语句。这两个相关结构的工作方式略有不同。


其次,即使您锁定同一个对象,您的代码仍然不会死锁(ideone)。内在锁是可重入的。这意味着如果线程尝试两次获取相同的锁,它不会自己死锁。

可重入同步

回想一下,一个线程不能获得另一个线程拥有的锁。但是线程可以获取它已经拥有的锁。允许一个线程多次获取同一个锁可以实现重入同步。这描述了一种情况,同步代码直接或间接调用一个也包含同步代码的方法,并且两组代码都使用相同的锁。如果没有可重入同步,同步代码将不得不采取许多额外的预防措施来避免线程导致自身阻塞。

来源

于 2012-04-19T22:30:35.530 回答
1

“当线程 t1 锁定静态对象 firstData 时,他获得了对类的锁定”
不知道你为什么这么认为。t1 获取 firstData 上的锁,而不是包含类的锁。您的代码中没有可能的死锁。

编辑
根据您的评论,链接是关于这两个声明之间的区别:

public synchronized method() // lock on the instance (this)
public static synchronized method() // lock on the class (Myclass.class)

但是与死锁没有联系。

于 2012-04-19T22:31:22.877 回答