Reputation: 75
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!
Upvotes: 7
Views: 179
Reputation: 5267
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.
Upvotes: 2
Reputation: 27190
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.
Upvotes: 11