这种方法可能会出现死锁吗?我该如何预防?

Is a deadlock possible in this method? How can I prevent it?

public void function(object a, object b){
    synchronized(a){
        synchronized (b){
           a.performAction(b);
           b.performAction(a);
        }
    }
}

2 个线程死锁? 感谢您的回答!

好的,

假设我们有两个对象,

Object one = ...;
Object two = ...;

假设线程 1 调用:

function(one, two);

当线程 2 调用时:

function(two, one);

在线程 1 中,a == oneb == two,但在线程 2 中,a == twob == one

因此,当线程 1 获取对象一的锁时,线程 2 可以获取对象二的锁。然后当每个线程都试图进行下一步时,它们就会死锁。

为了避免 jame 的回答中提到的问题,您需要创建一个锁来保存两个对象,无论它们传递给函数的顺序如何:

public class TwoObjectsLock {
    private Object a;
    private Object b;

    public TwoObjectsLock(Object a, Object b){
        this.a = a;
        this.b = b;
    }

    @Override
    public void equals(Object obj){
        if (this == obj) return true;
        if (obj instanceof TwoObjectsLock){
            TwoObjectsLock that = (TwoObjectsLock) obj;
            return (this.a.equals(that.a) && this.b.equals(that.b)) ||
                   (this.a.equals(that.b) && this.b.equals(that.a));
        }
        return false;
    }

    @Override
    public int hashCode(){
        return a.hashCode() + b.hashCode();
    }
}

并且在您的函数中,您需要以某种方式存储锁:

private final Map<TwoObjectsLock, TwoObjectsLock> lockInstances = new HashMap<>();

public void function(Object a, Object b){
    TwoObjectsLock lock = new TwoObjectsLock(a,b);
    synchronized(lockInstances){
        TwoObjectsLock otherLock = lockInstances.get(lock);
        if (otherLock == null){
            lockInstances.put(lock, lock);
        }
        else {
            lock = otherLock;
        }
    }

    synchronized(lock){
       a.performAction(b);
       b.performAction(a);
    }
}

不是最优但可以工作。