这段代码会导致死锁吗?

时间:2018-07-16 16:56:38

标签: java multithreading

我不太擅长多线程,并且对此代码感到困惑:

public class Main {
    public static void main(String... args) throws Exception {
        new Thread(Main::test).start();
    }

    private static synchronized void test() {
        new Thread(Main::test).start();
        System.out.println("TEST");
    }
}

会导致死锁吗?如果是这样,那我为何无法陷入僵局呢?我的想法是,线程1获取test()上的锁,然后在test()中创建的另一个线程尝试获取它,并且它们应该彼此等待。但是它们不是,为什么不呢?

我知道,在join()中添加test()会导致死锁,但是下面的示例为什么不使用联接和死锁?

每次我运行该代码都会导致死锁:

public class Main {
    public static void main(String... args) {
        new Thread(Main::test).start();
        new Thread(Main::test2).start();
    }

    private static void test() {
        synchronized (Integer.class) {
            try {
                Thread.sleep(1);
            } catch (Exception e) {
            }
            synchronized (Float.class) {
                System.out.println("Acquired float");
            }
        }
    }

    private static void test2() {
        synchronized (Float.class) {
            try {
                Thread.sleep(1);
            } catch (Exception e) {
            }
            synchronized (Integer.class) {
                System.out.println("Acquired integer");
            }
        }
    }
}

2 个答案:

答案 0 :(得分:3)

否,第一个示例中的代码无法死锁。新启动的线程将只是等待,直到前一个线程退出该方法以获取锁为止。

第二个示例中的代码死锁是因为以相反的顺序获取锁,并且由于睡眠将可靠地相互阻塞。

答案 1 :(得分:-1)

在您刚开始学习如何考虑并发性和相关问题的阶段时,我非常建议您使用物理道具来使您的思想和假设清晰明了。

例如,拿起一张A3纸,设置一条“跑道”,在其中您使用诸如Monopoly碎片之类的东西来表示您在代码中的工作,期望发生的事情以及实验实际显示的内容发生。

如果实验无法完成,请先从一小部分开始,然后进行验证。然后再添加一些,依此类推。

如果您阅读有关实际计算机(而不是CS理想计算机或概念计算机)当前工作方式的信息,将会很有帮助。 CPU如何将数据从主内存中获取到其缓存中。两个或三个CPU如何决定其中一个可以一次处理一条缓存行中的数据。然后,Java内存模型需要您如何编写源代码,以使JVM知道您实际上意味着什么。