【问题标题】:Why synchronized method cannot cause deadLock为什么同步方法不会导致死锁
【发布时间】:2020-10-18 07:27:28
【问题描述】:

我使用synchronized来测试deadLock,我发现synchronized不会通过在method上添加导致deadLock。代码如下:

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();
}

为什么同步方法不会导致死锁,总是循环执行。

【问题讨论】:

  • 可以,但是你的代码没有执行它。
  • 你的两个线程使用两个不同的锁。这怎么会导致死锁?

标签: java deadlock synchronized


【解决方案1】:

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

要导致死锁,两个线程应该请求另一个线程当前占用的资源。

此代码将成功陷入死锁!

public class DeadLock {
    public static void main(String[] args) {
        DeadLock t1 = new DeadLock();
        DeadLock t2 = new DeadLock();
        t1.setOther(t2);
        t2.setOther(t1);

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

    }

    private DeadLock other;
    public void setOther(DeadLock other) {
        this.other = other;
    }

    void print(String msg) {
        System.out.println(Thread.currentThread().getName() + msg);
    }

    synchronized void m1() {
        print(":m1 start");
        try {
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        print(":m1 waiting to get other.m1");
        other.m1();
    }
}

【讨论】:

    【解决方案2】:

    发生这种情况是因为 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();
        }
    }
    

    然后在相同DeadLock对象上调用这些方法。

    【讨论】:

      猜你喜欢
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 2015-03-09
      • 2019-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多