这种方法可能会出现死锁吗?我该如何预防?
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);
}
}
}
2 个线程死锁?
感谢您的回答!
好的,
假设我们有两个对象,
Object one = ...;
Object two = ...;
假设线程 1 调用:
function(one, two);
当线程 2 调用时:
function(two, one);
在线程 1 中,a == one
和 b == two
,但在线程 2 中,a == two
和 b == one
。
因此,当线程 1 获取对象一的锁时,线程 2 可以获取对象二的锁。然后当每个线程都试图进行下一步时,它们就会死锁。
为了避免 jame 的回答中提到的问题,您需要创建一个锁来保存两个对象,无论它们传递给函数的顺序如何:
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();
}
}
并且在您的函数中,您需要以某种方式存储锁:
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);
}
}
不是最优但可以工作。
public void function(object a, object b){
synchronized(a){
synchronized (b){
a.performAction(b);
b.performAction(a);
}
}
}
2 个线程死锁? 感谢您的回答!
好的,
假设我们有两个对象,
Object one = ...;
Object two = ...;
假设线程 1 调用:
function(one, two);
当线程 2 调用时:
function(two, one);
在线程 1 中,a == one
和 b == two
,但在线程 2 中,a == two
和 b == one
。
因此,当线程 1 获取对象一的锁时,线程 2 可以获取对象二的锁。然后当每个线程都试图进行下一步时,它们就会死锁。
为了避免 jame 的回答中提到的问题,您需要创建一个锁来保存两个对象,无论它们传递给函数的顺序如何:
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();
}
}
并且在您的函数中,您需要以某种方式存储锁:
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);
}
}
不是最优但可以工作。