To avoid the problem posed in response to jame, you need to create a single lock to store both objects, regardless of the order they pass to the function:
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(); } }
And in your function, you need to somehow save the lock:
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); } }
Not optimal, but may work.
source share