我发现经典的Java Deadlock
Tutorial
中包含对System.out.format的调用将防止死锁的发生,我不知道为什么。
下面的代码是相同的教程,与除main
的System.out.format("Hi, I'm %s...no deadlock for you!\n\n", alphonse.getName());
public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s has bowed to me!\n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!\n",
this.name, bower.getName());
}
}
public static void main(String[] args) throws InterruptedException {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
System.out.format("Hi, I'm %s...no deadlock for you!\n\n", alphonse.getName());
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
这是输出:
Hi, I'm Alphonse...no deadlock for you!
Alphonse: Gaston has bowed to me!
Gaston: Alphonse has bowed back to me!
Gaston: Alphonse has bowed to me!
Alphonse: Gaston has bowed back to me!
删除违规行会导致通常的死锁:
Alphonse: Gaston has bowed to me!
Gaston: Alphonse has bowed to me!
... deadlock ...
对System.out.format的调用是否以某种方式改变了线程获取对象内在锁的方式?
更新:
通过更改代码中启动线程的位置,我能够使系统再次陷入僵局:
public static void main(String[] args) throws InterruptedException {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
System.out.format("Hi, I'm %s...no deadlock for you!\n\n", alphonse.getName());
Thread t1 = new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
});
Thread t2 = new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
});
t1.start();
t2.start();
}
这就引出了一个问题,那就是我们如何才能更深入地了解线程调度程序的行为,但是我将其另存为另一天。
您并未真正消除 死锁 ,而是(由于某些内部JVM原因)更改了线程的计时,以使其中一个线程bowBack()
在 其他调用 之前
进入bow()
。只需输入bow
:sleep(1000)
,您的僵局就会再次出现。
请注意,只有在线程处于 幸运 时机时,死锁并不 总是 发生。在这种情况下,当两个线程都进入并且它们中的任何一个都调用之前,就会发生死锁
__bow``bowBack
…并且 “某些内部JVM原因” 可以如下:
在您的情况下,实际上有三个线程:一个执行 main , t1 和 t2 。放置 打印
隐藏死锁的原因可能是线程调度程序决定main
仍有工作要做,即刷新io缓冲区,因此让 main 在开始 t1之后
和开始t2之前继续。如果你是一个双核CPU,只main
和t1
会运行,但t2
会等待,因为print
是一个缓慢的操作。上下文切换将花费更多时间,并且
t1 将在 t2 之前完成 __可以开始…所以不会发生死锁。 但这并不意味着如果再次运行该程序,就不会发生死锁。
If you want to play, create a queue
and push tokens (thread names) in that
queue, then join
your threads in main. After they finish, print the queue
content and you can observe the timing of the threads.
本文向大家介绍怎么防止死锁?相关面试题,主要包含被问及怎么防止死锁?时的应答技巧和注意事项,需要的朋友参考一下 尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。 尽量使用 Java. util. concurrent 并发类代替自己手写锁。 尽量
问题 你正在写一个多线程程序,其中线程需要一次获取多个锁,此时如何避免死锁问题。 解决方案 在多线程程序中,死锁问题很大一部分是由于线程同时获取多个锁造成的。举个例子:一个线程获取了第一个锁,然后在获取第二个锁的 时候发生阻塞,那么这个线程就可能阻塞其他线程的执行,从而导致整个程序假死。 解决死锁问题的一种方案是为程序中的每一个锁分配一个唯一的id,然后只允许按照升序规则来使用多个锁,这个规则使用
我有一个用PHP编写的守护进程(不是最好的语言,但与我一起工作),它用于从队列接收作业,并在需要完成作业时处理它们。对于每个新作业,我使用pcntl_fork()将作业分叉到子进程中。在这个子进程中,我然后使用proc_open()执行用于音频转码的长时间运行的系统命令,完成后直接返回到子进程。作业完成后,子进程退出并由父进程清理。 为了保持这个守护进程始终运行,我使用upstart。这是我的暴发
[注意:这与如何从Java程序启动完全独立的进程有关?但不同] 我希望能够从一个“管理器”Java进程中派生出外部进程(shell脚本),当JVM被杀死时,该进程应该继续运行——但当我杀死父Java程序时,子Java程序似乎也被杀死(注意,如果JVM自然退出,行为会有所不同)。我拥有的最简单的测试程序是: 和外部脚本: 作为 java-带有依赖项的类路径jar。罐子温度。执行官。快跑快跑。嘘 如果
我正在使用Javaexec运行bash脚本,但当我进入CTRL C时,Java进程将退出,子进程也将退出,如何在JVM关闭后保持子进程运行? 父母亲上海: 我已经在这里和这里阅读了类似问题的答案,例如,使用nohup在脚本运行命令中启动父bash脚本,或者使用trap命令来阻止信号,在我的研究中,它可以工作,例如“tail-f somefile”,但不适用于我的用例“ffmpeg-params”,
在Java类的总体描述中,我遇到了这样一行:“然而,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表”。我的问题是:这是否意味着并发HasMap不能防止死锁?我还认为线程安全意味着不会发生死锁?