MrBoolean
MrBoolean

Reputation: 75

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);
        }
    }
}

Deadlock with 2 Threads? Thanks for the answers!

Upvotes: 7

Views: 179

Answers (2)

Gilberto Torrezan
Gilberto Torrezan

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

Solomon Slow
Solomon Slow

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

Related Questions