public void function(object a, object b){
synchronized(a){
synchronized (b){
a.performAction(b);
b.performAction(a);
}
}
}
Deadlock with 2 Threads? Thanks for the answers!
public void function(object a, object b){
synchronized(a){
synchronized (b){
a.performAction(b);
b.performAction(a);
}
}
}
Deadlock with 2 Threads? Thanks for the answers!
Sure,
Suppose we have two objects,
Object one = ...;
Object two = ...;
And suppose thread 1 calls:
function(one, two);
While thread 2 calls:
function(two, one);
In thread 1, a == one
and b == two
, but in thread 2, a == two
and b == one
.
So while thread 1 is obtaining a lock on object one, thread 2 can be obtaining the lock on object two. Then when each of the threads tries to take the next step, they will be deadlocked.
To avoid the problem stated by jame's answer, you need to create a single lock to hold both objects, no matter the order they are passed 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 store the lock somehow:
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 can work.