Java 僵局在哪里?
这是java文档中关于死锁的教程。我不知道线程被阻塞的地方。因为它是同步的,我想只有一根线会进入弓。但两人都进了船头。[等待[但何时?]] 那么问题在哪里呢 当我添加注释[将语句打印到跟踪]时。没有僵局。怎么做Java 僵局在哪里?,java,multithreading,Java,Multithreading,这是java文档中关于死锁的教程。我不知道线程被阻塞的地方。因为它是同步的,我想只有一根线会进入弓。但两人都进了船头。[等待[但何时?]] 那么问题在哪里呢 当我添加注释[将语句打印到跟踪]时。没有僵局。怎么做 public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name
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) {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("Thread 1");
alphonse.bow(gaston);
// System.out.println("Th: gaston bowed to alphonse");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("Thread 2");
gaston.bow(alphonse);
// System.out.println("2.gaston waiting alph bowed");
}
}).start();
}
}
输出为:
Alphonse: Gaston has bowed to me!
Gaston: Alphonse has bowed to me!
没有人会退缩 这里有两个独立的对象-synchronized关键字不会阻止在对象1中与在对象2中同时调用bow。它只会阻止两个线程进入同一对象的同步方法
然后输入两个方法,每个对象上都有锁。然后,两者都不能输入另一个对象的方法,因为同步关键字在对象级别上工作。您在那里有两个单独的对象-同步关键字不会阻止在对象1中与在对象2中同时调用bow。它只会阻止两个线程进入同一对象的同步方法
然后输入两个方法,每个对象上都有锁。然后两者都不能进入另一个对象的方法,因为同步关键字在对象级别工作。首先,调用
System.out.println()
会带来大量资源,因此会在处理过程中造成有效延迟,从而人为地导致/避免并发问题。不要过多地了解添加打印的效果
现在,当线程a锁X然后锁Y,同时线程B锁Y然后锁X时,就会发生死锁。如果两个线程都获得了第一个锁,那么两个线程都不能继续=死锁
在您的例子中,方法
bow()
锁定它所调用的实例,但是从该锁中调用bowe的bow方法:同步是锁定实例,因此两个单独的实例都可以获得它们的第一个锁。第二个锁在另一个实例上,因此两个线程都在等待另一个线程持有的锁=死锁。首先,调用System.out.println()
会带来大量资源,因此会在处理过程中产生有效延迟,从而人为地导致/避免并发问题。不要过多地了解添加打印的效果
现在,当线程a锁X然后锁Y,同时线程B锁Y然后锁X时,就会发生死锁。如果两个线程都获得了第一个锁,那么两个线程都不能继续=死锁
在您的例子中,方法
bow()
锁定它所调用的实例,但是从该锁中调用bowe的bow方法:同步是锁定实例,因此两个单独的实例都可以获得它们的第一个锁。第二个锁位于另一个实例上,因此两个线程都在等待另一个线程持有的锁=死锁。对此进行了精确解释。由于第一个对象试图调用第二个对象上的某个对象,第二个对象在到达同步块后一直在等待,所以对bowBack()的第一个调用永远不会结束,两个调用都会被卡住。读这篇文章。第一次我没有注意到你在从另一个对象调用bower.getName()
bower.getName()
调用导致死锁解释得很清楚。由于第一个对象试图调用第二个对象上的某个对象,第二个对象在到达同步块后一直在等待,所以对bowBack()的第一个调用永远不会结束,两个调用都会被卡住。读这篇文章。第一次我没有注意到你在从另一个对象调用bower.getName()
bower.getName()
调用导致死锁考虑到某个时间点,“Alphonse”和“Gaston”都开始鞠躬,这意味着它们已经分别拥有了自己的锁。然后他们都希望另一方同时向对方鞠躬,这意味着他们都试图获得对方的锁。由于两个锁都被占用,因此bowBack()
调用将被阻止。由于bowBack()
在bow()
块中,因此bow()
函数不能立即返回。因此,当他们已经获得了一些资源,但仍然试图获得一些已经占用的其他资源时,他们处于僵局状态。考虑到某个时间点,“阿尔方斯”和“加斯顿”都开始鞠躬,这意味着他们已经分别拥有了自己的锁。然后他们都希望另一方同时向对方鞠躬,这意味着他们都试图获得对方的锁。由于两个锁都被占用,因此bowBack()
调用将被阻止。由于bowBack()
在bow()
块中,因此bow()
函数不能立即返回。因此,当他们已经获得一些资源,但仍然试图获得一些已经占用的其他资源时,他们就处于死锁状态。这里需要了解两件重要的事情:1)每个并发运行的线程在做什么?2)涉及哪些锁
首先,您创建了Friend类的两个实例:alphonse和gaston。每个对象都有自己的锁。所以有两种锁:阿尔方斯锁和加斯顿锁。当您输入对象的同步方法时,它会锁定该对象的锁。当同步方法返回时,锁被释放(解锁)
现在是线程。您的第一个线程,我们称之为Alphone的线程(注意大写字母A以区分线程和对象,alphonse)执行以下操作:(“A:”表示这是alphonse的线程。)
同时,Gaston的线程执行以下操作:(“G:”表示这是Gaston的线程。)
现在我们可以把这两个信息放在一起,得出我们的答案。线程可以以不同的顺序交错(即,它们的事件发生)。例如,如果事件按以下顺序发生,则会发生死锁:
A: alphonse.bow(gaston) - acquires alphonse's lock
G: gaston.bow(alphonse) - acquires gaston's lock
G: attempts to call alphonse.bowBack(gaston), but blocks waiting on alphonse's lock
A: attempts to call gaston.bowBack(alphonse), but blocks waiting on gaston's lock to
在这种情况下,每个线程都被阻塞,等待获取
G: gaston.bow(alphonse) - acquires gaston's lock
G: alphonse.bowBack(gaston) - acquires alphonse's lock
G: both methods return, thus releasing both locks
A: alphonse.bow(gaston) - acquires alphonse's lock
G: gaston.bow(alphonse) - acquires gaston's lock
G: attempts to call alphonse.bowBack(gaston), but blocks waiting on alphonse's lock
A: attempts to call gaston.bowBack(alphonse), but blocks waiting on gaston's lock to
A: alphonse.bow(gaston) - acquires alphonse's lock
A: gaston.bowBack(alphonse) - acquires gaston's lock
A: both methods return, thus releasing both locks
G: gaston.bow(alphonse) - acquires gaston's lock
G: alphonse.bowBack(gaston) - acquires alphonse's lock
G: both methods return, thus releasing both locks