SharedArray Deadlock и повышение условий - PullRequest
0 голосов
/ 21 мая 2019

Я пытаюсь стимулировать сценарий взаимоблокировок в разделяемом массиве с помощью 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(); 
    }       
}

Здесь метод обмена является тупиковым, которого я достиг. например, если поток 1 - это своп (7,4), и в то же время поток 2 - это своп (4,7), это вызовет тупик.

Как мне предотвратить его тупик. Какой рефакторинг требуется. Я пытался использовать синхронизированный, но я ищу, возможно, надежный способ решить эту проблему.

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

Ответы [ 2 ]

0 голосов
/ 21 мая 2019

Вы хотите использовать порядок блокировки. Если вы блокируете каждый раз в предсказуемом порядке, вы можете предотвратить мертвую блокировку.

Находится в Java Concurrency На практике вы можете увидеть пример того, как этого добиться:

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, поиск по листингу 10.3. Создание блокировки, чтобы избежать тупика.

0 голосов
/ 21 мая 2019

Как мне предотвратить тупик?

Одним из способов предотвращения тупиковой ситуации было бы обеспечение того, чтобы все потоки, которые получают одинаковые две блокировки, всегда получали их в одном и том же порядке.

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