Java 为什么同步方法不能导致死锁

Java 为什么同步方法不能导致死锁,java,deadlock,synchronized,Java,Deadlock,Synchronized,我使用synchronized来测试死锁,我发现synchronized不能通过在方法上添加它来导致死锁。代码如下: public static void main(String[] args) { DeadLock t1 = new DeadLock(); DeadLock t2 = new DeadLock(); new Thread(() -> { t1.m1(); }).start(); new Thread(() ->

我使用synchronized来测试死锁,我发现synchronized不能通过在方法上添加它来导致死锁。代码如下:

public static void main(String[] args) {

    DeadLock t1 = new DeadLock();
    DeadLock t2 = new DeadLock();
    new Thread(() -> {
        t1.m1();
    }).start();
    new Thread(() -> {
        t2.m1();
    }).start();


}

synchronized void m1() {
    System.out.println(Thread.currentThread().getName() + ":m1 start");
    try {
        TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + ":m1 waiting to get m2");
    m2();
}

synchronized void m2() {
    System.out.println(Thread.currentThread().getName() + ":m2 start");
    try {
        TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + ":m2 waiting to get m1");
    m1();
}
为什么同步方法不能导致死锁,它总是在一个循环中执行。

您正在两个不同的实例上调用
m1()
方法
synchronized
关键字阻止从多个同步块/方法对同一对象的并发访问

要造成死锁,两个线程应该要求另一个线程当前占用的资源

此代码将成功捕获死锁

公共类死锁{
公共静态void main(字符串[]args){
死锁t1=新死锁();
死锁t2=新死锁();
t1.其他组(t2);
t2.其他组(t1);
新线程(()->{
t1.m1();
}).start();
新线程(()->{
t2.m1();
}).start();
}
私人僵局;其他;
公共无效设置其他(死锁其他){
this.other=其他;
}
无效打印(字符串消息){
System.out.println(Thread.currentThread().getName()+msg);
}
同步的void m1(){
打印(“:m1开始”);
试一试{
时间单位。毫秒。睡眠(1);
}捕捉(中断异常e){
e、 printStackTrace();
}
打印(“:m1等待获取其他.m1”);
其他。m1();
}
}

发生这种情况是因为Java中的隐式对象监视器锁是可重入的。也就是说,如果线程在对象上持有隐式监视器锁,它将能够执行由该锁保护的任何代码段。当线程进入
m1()
时,它能够进入
m2()
(反之亦然),因为它已经拥有锁。这将无限期地持续下去

要演示死锁,您必须使用两种不同锁的方法,如下所示:

void m1() {
    synchronized(obj1) {
        System.out.println(Thread.currentThread().getName() + ":m1 start");
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":m1 waiting to get m2");
        m2();
    }
}

void m2() {
    synchronized(obj2) {
        System.out.println(Thread.currentThread().getName() + ":m2 start");
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":m2 waiting to get m1");
        m1();
    }
}

然后在同一个
死锁
对象上调用这些方法。

可以,但代码不执行它。您的两个线程使用两个不同的锁。这怎么会导致僵局?