0

I'm trying to stimulate the scenario of deadlocks in the shared array using Reentrant Locks.

class SharedArray { 
    private int ff[];
    private Lock keys[];        

    public SharedArray(int n){
        ff = new int[n];
        keys = new ReentrantLock[n];
        for(int j = 0; j < n; j++){
            ff[j] = (int)(Math.random()*100);
            keys[j] = new ReentrantLock();
        }
    }

    void swap(int j, int k) { 
        keys[j].lock(); keys[k].lock(); 
        int t = ff[j]; ff[j] = ff[k]; ff[k] = t;
        keys[j].unlock(); keys[k].unlock(); 
    }       
}

Here the swap method is deadlock prone which I have achieved. for example if Thread 1 is swap(7,4) and at the same time Thread 2 is swap(4,7) this will raised the deadlock.

How do I prevent it from deadlock. What sort of refactoring is required. I have tried to used synchronized but I'm looking for possibly a reliable way to solve that.

synchronized void swap(int j, int k) { 
    keys[j].lock(); keys[k].lock(); 
    int t = ff[j]; ff[j] = ff[k]; ff[k] = t;
    keys[j].unlock(); keys[k].unlock(); 
} 
Hassaan
  • 3,931
  • 11
  • 34
  • 67

2 Answers2

0

How do I prevent it from deadlock?

One way to prevent deadlock would be to ensure that any threads that acquire the same two locks always will acquire them in the same order.

void swap(int j, int k) {
    int first = Math.min(j, k);
    int second = Math.max(j, k);
    keys[first].lock(); keys[second].lock(); 
    int t = ff[j]; ff[j] = ff[k]; ff[k] = t;
    keys[second].unlock(); keys[first].unlock(); 
}
Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

You want to employ lock ordering. If you lock each time in a predictable order you can prevent dead locking.

Found in Java Concurrency In Practice, you can see an example of how to achieve this:

public void transferMoney(final Account fromAcct, final Account toAcct, final DollarAmount amount)
        throws InsufficientFundsException {
    class Helper {
        public void transfer() throws InsufficientFundsException {
            if (fromAcct.getBalance().compareTo(amount) < 0)
                throw new InsufficientFundsException();
            else {
                fromAcct.debit(amount);
                toAcct.credit(amount);
            }
        }
    }
    int fromHash = System.identityHashCode(fromAcct);
    int toHash = System.identityHashCode(toAcct);
    if (fromHash < toHash) {
        synchronized (fromAcct) {
            synchronized (toAcct) {
                new Helper().transfer();
            }
        }
    } else if (fromHash > toHash) {
        synchronized (toAcct) {
            synchronized (fromAcct) {
                new Helper().transfer();
            }
        }
    } else {
        synchronized (tieLock) {
            synchronized (fromAcct) {
                synchronized (toAcct) {
                    new Helper().transfer();
                }
            }
        }
    }
}

https://pdfs.semanticscholar.org/3650/4bc31d3b2c5c00e5bfee28ffc5d403cc8edd.pdf, search for Listing 10.3. Inducing a Lock Ordering to Avoid Deadlock.

John Vint
  • 39,695
  • 7
  • 78
  • 108