Java 在这种方法中是否可能出现死锁?我怎样才能预防它?
死锁与两个线程? 谢谢你的回答 当然 假设我们有两个物体Java 在这种方法中是否可能出现死锁?我怎样才能预防它?,java,deadlock,Java,Deadlock,死锁与两个线程? 谢谢你的回答 当然 假设我们有两个物体 public void function(object a, object b){ synchronized(a){ synchronized (b){ a.performAction(b); b.performAction(a); } } } 假设线程1调用: Object one = ...; Object two = ...; 线程2调用
public void function(object a, object b){
synchronized(a){
synchronized (b){
a.performAction(b);
b.performAction(a);
}
}
}
假设线程1调用:
Object one = ...;
Object two = ...;
线程2调用时:
function(one, two);
在线程1中,a==1
和b==2
,但在线程2中,a==2
和b==1
因此,当线程1在对象1上获得锁时,线程2可以在对象2上获得锁。然后,当每个线程尝试执行下一步时,它们将处于死锁状态。为了避免jame回答中所述的问题,您需要创建一个锁来保存这两个对象,无论它们传递给函数的顺序如何:
function(two, one);
在函数中,您需要以某种方式存储锁:
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 lockInstances=new HashMap();
公共无效功能(对象a、对象b){
TwoObjectsLock=新TwoObjectsLock(a,b);
已同步(锁定实例){
TwoObjectsLock otherLock=lockInstances.get(lock);
if(otherLock==null){
lockInstances.put(锁,锁);
}
否则{
lock=otherLock;
}
}
已同步(锁定){
a、 执行(b);
b、 执行(a);
}
}
不是最佳,但可以工作。否,两个线程都将等待“a”。这可能是因为有第二种方法,您首先在“b”上同步,然后在“a”上同步是否在同步方法中使用对象a?例如,会出现死锁?在提供的情况下否,因为线程1将等待对象“a”的释放,直到方法结束。实际上,我认为如果两个线程使用对象thread1(a,b)和线程2(b,a)执行funktion同时出现死锁,因为两个线程都在等待第二次同步中的对象,或者我错了吗?线程1(a,b)和线程2(b,a)-在这种情况下,是的,您可以通过按asc/desc哈希代码顺序锁定来修复。不管怎么说,这不好。
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);
}
}