Java 并发-为什么会出现这种死锁
嗯。我在理解并发的基础知识方面遇到了一些困难。这个问题是关于僵局的。请告诉我为什么这两个线程都以死锁结束 我从教程中选取了这个例子。它说 当死锁运行时,两个线程在试图调用bowBack时很可能都会阻塞。两个阻塞都不会结束,因为每个线程都在等待另一个线程退出bow 我的理解是:首先,它们会等待,因为当线程调用同步方法时,它会自动获取同步方法所属对象的内在锁,并继续拥有它,直到方法返回;同时,没有其他线程可以拥有它 1。现在我的第一个问题是第一个线程调用zarah.bow(),因此内在锁与zarah关联。第二个线程将调用khan.bow(),这将是一个不同的内在锁(因为它与另一个名为khan的对象相关联),不是吗? 扎拉·鲍和汗·鲍不是不同吗?因为它们属于两个不同的实例? 2。第二个问题来自“两个”线程永远等待的概念。两条线将永远被阻塞,等待对方退出弓。我不明白。Java 并发-为什么会出现这种死锁,java,multithreading,concurrency,Java,Multithreading,Concurrency,嗯。我在理解并发的基础知识方面遇到了一些困难。这个问题是关于僵局的。请告诉我为什么这两个线程都以死锁结束 我从教程中选取了这个例子。它说 当死锁运行时,两个线程在试图调用bowBack时很可能都会阻塞。两个阻塞都不会结束,因为每个线程都在等待另一个线程退出bow 我的理解是:首先,它们会等待,因为当线程调用同步方法时,它会自动获取同步方法所属对象的内在锁,并继续拥有它,直到方法返回;同时,没有其他线程可以拥有它 1。现在我的第一个问题是第一个线程调用zarah.bow(),因此内在锁与zarah
package Threads;
public class DeadlockModified {
static class Friend {
private final String name;
Friend(String name){
this.name=name;
}
private String getName(){
return this.name;
}
private synchronized void bow(Friend bower){
System.out.format("%s: %s"+" bowed to me.%n",bower.getName(),name);
bower.bowBack(this);
}
private synchronized void bowBack(Friend bower){
System.out.format("%s: %s" + " was nice enough to bow back to me.%n",bower.getName() ,name );
}
}
public static void main(String [] args){
final Friend zarah= new Friend("Zarah");
final Friend khan= new Friend("Khan");
new Thread(new Runnable(){
public void run(){zarah.bow(khan);}
}).start();
new Thread(new Runnable() {
public void run(){khan.bow(zarah);}
}).start();
}
}
输出:-
Khan: Zarah bowed to me.
Zarah: Khan bowed to me.
先谢谢你
编辑:-
在本教程的“同步方法”一节中,作者写道
“从同步代码调用其他对象的方法可能会产生问题,这些问题将在“活动性”一节中介绍。”
这是关于活力的部分。我看到另一个对象的方法bowBack()正在从bow()调用。还有一些问题-查看程序的输出,看起来两个线程都没有执行bowBack()。但是没有给出更多的细节。- 线程1调用
:它获取zarah.bow(khan)
zarah
- 线程2调用
:它获取khan.bow(zarah)
khan
- 线程1试图调用
:它需要khan的内在锁才能做到这一点。但是这个锁由线程2持有。因此线程1等待线程1释放khan的锁khan.bowBack()
- 线程2尝试调用
:它需要zarah的内在锁才能做到这一点。但是这个锁由线程1持有。因此线程2等待线程1释放zarah的锁zarah.bowBack()
- 线程1调用
:它获取zarah.bow(khan)
zarah
- 线程2调用
:它获取khan.bow(zarah)
khan
- 线程1试图调用
:它需要khan的内在锁才能做到这一点。但是这个锁由线程2持有。因此线程1等待线程1释放khan的锁khan.bowBack()
- 线程2尝试调用
:它需要zarah的内在锁才能做到这一点。但是这个锁由线程1持有。因此线程2等待线程1释放zarah的锁zarah.bowBack()
bow()
的调用在不同的实例上执行,但在内部,它们在另一个实例上调用bowBack()
,并且该调用也是同步的
示例:zarah.bow()
将同步zarah
(即调用它的实例)以及bower.bowBack(此)
在调用khan.bow(zarah)
中,因为这也可以被理解为zarah.bowBack(khan)
(bower=zarah
和this=khan
)
两条线将永远被阻塞,等待对方退出弓
如果没有任何机制来中断其中一个线程,那么两个线程都将等待另一个线程离开同步部分,并且由于它们都在自己的同步块中等待,因此它们永远不会离开
关于死锁的一个很好的非技术性例子是。每一位哲学家都是“哲学家”类的“实例”,在等待其他人释放他们在叉子上的锁的同时,会在他的叉子上持有自己固有的锁
zarah.bow()和khan.bow()不一样吗
是的,对bow()
的调用在不同的实例上执行,但在内部,它们在另一个实例上调用bowBack()
,并且该调用也是同步的
示例:zarah.bow()
将同步zarah
(即调用它的实例)以及bower.bowBack(此)
在调用khan.bow(zarah)
中,因为这也可以被理解为zarah.bowBack(khan)
(bower=zarah
和this=khan
)
两条线将永远被阻塞,等待对方退出弓
如果没有任何机制来中断其中一个线程,那么两个线程都将等待另一个线程离开同步部分,并且由于它们都在自己的同步块中等待,因此它们永远不会离开
关于死锁的一个很好的非技术性例子是。每个哲学家都是“哲学家”类的一个“实例”,在等待其他人释放其叉子上的锁时,会在其叉子上持有自己的固有锁。为了确保您真正理解这一点,请尝试使用该习语重写这些方法
synchronized(Object){
enter code here
}
这将获得上的内在锁
synchronized(bower){
System.out.format("%s: %s"+" bowed to me.%n",bower.getName(),name);
bower.bowBack(this);
}
static class proxyLock(){};
private void bow(proxyLock lock, Friend bower){
synchronized(lock){
System.out.format("%s: %s"+" bowed to me.%n",bower.getName(),name);
bower.bowBack(this);
}
}