如何在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