如何在java中防止这种简单的死锁?
我举了一个简单的例子来说明如何导致死锁:如何在java中防止这种简单的死锁?,java,concurrency,deadlock,Java,Concurrency,Deadlock,我举了一个简单的例子来说明如何导致死锁: class Player { private String name; public Player(String name) { super(); this.name = name; } public synchronized void passTo(Player p) { System.out.println(this.name + " passes to " + p.
class Player {
private String name;
public Player(String name) {
super();
this.name = name;
}
public synchronized void passTo(Player p) {
System.out.println(this.name + " passes to " + p.name);
// to imitate long task
for (int i = 0; i < 1000000000; i++)
;
p.passBack(this);
}
private synchronized void passBack(Player p) {
System.out.println(this.name + " passes back to " + p.name);
}
}
public class Deadlock {
public static void main(String[] args) {
final Player ivan = new Player("Ivan");
final Player petro = new Player("Petro");
new Thread(new Runnable() {
public void run() {
ivan.passTo(petro);
}
}).start();
new Thread(new Runnable() {
public void run() {
petro.passTo(ivan);
}
}).start();
}
}
职业玩家{
私有字符串名称;
公共播放器(字符串名称){
超级();
this.name=名称;
}
公共同步无效通行证(玩家p){
System.out.println(this.name+“传递到”+p.name);
//模仿长任务
对于(int i=0;i<100000000;i++)
;
p、 逾越节(本节);
}
私人同步无效回传(玩家p){
System.out.println(this.name+“传递回”+p.name);
}
}
公共类死锁{
公共静态void main(字符串[]args){
最终玩家伊万=新玩家(“伊万”);
最终玩家petro=新玩家(“petro”);
新线程(newrunnable()){
公开募捐{
伊万·帕斯托(石油);
}
}).start();
新线程(newrunnable()){
公开募捐{
帕斯托石油公司(伊万);
}
}).start();
}
}
当我运行这个程序时,它会导致死锁
有哪些可能的解决方案可以防止这种简单的死锁
谢谢大家! 您可以将
public synchronized void passTo(Player p)
方法设置为静态。因此,一次只有一个玩家可以调用passTo()
方法,并且不会出现死锁,即移除循环依赖。所以把它改成
public static synchronized void passTo(Player p)
您需要锁定独立于类对象的对象,并且该对象本身就是class
要获得类
本身的锁,必须使方法静态
以及同步
示例代码:(根据您的要求调整代码)
输出:
Ivan passes to Petro
Ivan passes back to Petro
Petro passes to Ivan
Petro passes back to Ivan
不使用synchronized关键字?在你的情况下,你只有一个球。因此,在进行第二次传递之前,必须完成第一次传递。这是正确的做法。为了使其无缝,请减少其调用量。或者减少所需的时间。现在似乎做的是对的。为什么需要将
passBack
发送到同步服务器?它是私有的,只能从passTo
调用。演示的目的是展示死锁是如何发生的。代码中没有死锁。要产生死锁,passBack()方法必须调用passTo()。然后这些方法将互相等待。在您的情况下,总是首先调用passTo(),永远不会出现死锁。此
用于passTo()
和passBack()
方法。这就是为什么获得的锁将是实例级锁,这将导致死锁。要解决此问题,您需要获得类级锁。所以,即使有两个播放器实例,一次也只有一个会得到锁,避免死锁。
Ivan passes to Petro
Ivan passes back to Petro
Petro passes to Ivan
Petro passes back to Ivan