我不太擅长多线程,并且对此代码感到困惑:
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");
}
}
}
}
答案 0 :(得分:3)
否,第一个示例中的代码无法死锁。新启动的线程将只是等待,直到前一个线程退出该方法以获取锁为止。
第二个示例中的代码死锁是因为以相反的顺序获取锁,并且由于睡眠将可靠地相互阻塞。
答案 1 :(得分:-1)
在您刚开始学习如何考虑并发性和相关问题的阶段时,我非常建议您使用物理道具来使您的思想和假设清晰明了。
例如,拿起一张A3纸,设置一条“跑道”,在其中您使用诸如Monopoly碎片之类的东西来表示您在代码中的工作,期望发生的事情以及实验实际显示的内容发生。
如果实验无法完成,请先从一小部分开始,然后进行验证。然后再添加一些,依此类推。
如果您阅读有关实际计算机(而不是CS理想计算机或概念计算机)当前工作方式的信息,将会很有帮助。 CPU如何将数据从主内存中获取到其缓存中。两个或三个CPU如何决定其中一个可以一次处理一条缓存行中的数据。然后,Java内存模型需要您如何编写源代码,以使JVM知道您实际上意味着什么。