这段代码会导致死锁吗



我不太擅长多线程,对以下代码感到困惑:

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()中创建的另一个线程试图获取它,它们应该相互等待。但他们不是,为什么不呢?

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

这段代码每次运行都会导致死锁:

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

不,第一个例子中的代码不能死锁。新启动的线程将简单地等待,直到上一个线程退出该方法以获取锁。

第二个示例中的代码会死锁,因为锁是按相反的顺序获取的,而且睡眠会可靠地相互阻塞。

当你处于第一次学习如何思考并发和相关问题的阶段时,我非常建议你使用物理道具来保持你的想法和假设清晰明确。

例如,拿一张A3纸,设置一个"赛道",在那里你可以使用类似"大富翁"的东西来表示你在代码中正在做什么,你期望发生什么,以及你的实验显示实际发生了什么。

当你的实验不成功时,先从开头取一小块,然后验证。然后再加一些,以此类推。

如果你读到实际计算机(而不是CS理想或概念计算机(目前是如何工作的,这会有所帮助。CPU如何将数据从主内存中取出并放入缓存。两个或三个CPU如何决定其中哪一个可以一次处理一个缓存行中的数据。然后,Java内存模型需要您如何编写源代码,以便JVM知道您的实际意图。

最新更新