我正在尝试使用可重入锁来模拟共享数组中的死锁场景。
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();
} 发布于 2019-05-21 21:49:35
如何防止死锁?
防止死锁的一种方法是确保获取相同两个锁的任何线程始终以相同的顺序获取它们。
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();
}发布于 2019-05-21 21:51:46
您想要使用锁排序。如果您每次都以可预测的顺序锁定,则可以防止死锁。
在Java并发性实践中,您可以看到一个如何实现这一点的示例:
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。诱导Lock排序以避免死锁。
https://stackoverflow.com/questions/56237133
复制相似问题