请参阅以下代码
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
method2();
}
}
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
根据我的理解,method2
中的代码不应该在任何情况下执行,因为method1
持有Integer.class
上的锁,method2
尝试访问锁定再次Integer.class
。但令我惊讶的是,代码运行良好,并在控制台上打印“hi there”。有人可以澄清吗?
答案 0 :(得分:4)
锁是由线程拥有的。如果你的线程已经拥有一个锁,那么Java假定你不需要再次获取它而只是继续。
如果在保持锁定的同时在method1()
中启动第二个线程并且第二个线程执行方法method2()
,则会出现死锁。
如果您更喜欢代码,那么synchronized
的工作原理如下:
Lock lock = Integer.class.getLock();
boolean acquired = false;
try {
if(lock.owner != Thread.currentThread()) {
lock.acquire();
acquired = true;
}
...code inside of synchronized block...
} finally {
if(acquired) lock.release();
}
这是演示死锁的代码。只需将runInThread
设置为true
:
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
boolean runInThread = false;
if( runInThread ) {
Thread t = new Thread() {
@Override
public void run() {
method2();
}
};
t.start();
try {
t.join(); // this never returns
} catch( InterruptedException e ) {
e.printStackTrace();
}
} else {
method2();
}
}
}
private void method2() {
System.out.println("trying to lock");
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
答案 1 :(得分:3)
似乎你误解了这个概念。 方法永远不会获取锁,调用该方法的实例在同步方法的情况下用作锁,在同步块的情况下,线程获取对指定对象的锁。
这里实例获取Integer.class上的锁,然后继续执行method2。
没有死锁的情况,因为你的情况下线程继续执行你在method1中调用的方法。所以没有发生死锁。
答案 2 :(得分:0)
您的代码相当于:
synchronized (Integer.class) {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
如果线程获得了锁并进入了第一个synchronized
块,那么访问第二个
产生死锁,对method2的调用应该由不同的线程执行。
答案 3 :(得分:0)
synchronized (Integer.class) {
method2();
}
当你调用这个method2();
时它没有锁定任何类型的mehtod,它继续转到你正在调用的方法意味着这个。
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
并在完成返回后。所以没有死锁的情况。希望这个解释有所帮助。
答案 4 :(得分:0)
如前所述,当没有其他线程已经阻止它时,一个线程可以访问多个同步块。在那种情况下,同一个线程可以重新输入synchronized块,因为它已经从method1保存它。
要导致死锁,您必须至少使用两个线程和两个不同的锁。它必须以相反的顺序访问两个锁。看看代码:
private void method1() throws InterruptedException
{
synchronized (Integer.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 1");
Thread.sleep(1000);
method2();
}
}
private void method2() throws InterruptedException
{
synchronized (Double.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 2");
Thread.sleep(1000);
method1();
}
}
public static void main(String[] args) throws InterruptedException
{
new Thread()
{
@Override
public void run()
{
try
{
new DeadLock().method1();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}.start();
new DeadLock().method2();
}