根据我的理解,下面这段代码会导致死锁。 原因是,当线程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");
}
}
}
}
对于那些回答说锁是对象而不是课堂的人,请看一下this
答案 0 :(得分:14)
首先,你在这里犯了错误:
原因是,当线程t1锁定静态对象firstData时,他已经获得了对该类的锁定。
锁定静态对象仅锁定该对象,而不是类。您正在锁定两个单独的对象。
question you refered to约为synchronized methods而不是synchronized statements。这两个相关结构的工作方式略有不同。
其次,即使您锁定了同一个对象,您的代码仍然不会死锁(ideone)。内部锁是可重入。这意味着如果一个线程尝试两次使用相同的锁,它就不会死锁。
可重入同步
回想一下,线程无法获取另一个线程拥有的锁。但是一个线程可以获得它已经拥有的锁。允许线程多次获取相同的锁可启用重入同步。这描述了一种情况,其中同步代码直接或间接地调用也包含同步代码的方法,并且两组代码使用相同的锁。如果没有可重入同步,同步代码必须采取许多额外的预防措施,以避免线程导致自身阻塞。
答案 1 :(得分:1)
“当线程t1锁定静态对象firstData时,他已经获得了对类的锁定” 不确定你为什么这么认为。 t1获取firstData上的锁,而不是包含类。代码中没有可能的死锁。
修改强>
在您的评论之后,链接是关于这两个声明之间的区别:
public synchronized method() // lock on the instance (this)
public static synchronized method() // lock on the class (Myclass.class)
但是没有死锁的链接。