Để tránh những vấn đề đã nêu bởi câu trả lời Jame, bạn cần phải tạo ra một khóa duy nhất để giữ cả hai đối tượng, bất kể thứ tự mà chúng được truyền cho hàm:
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();
}
}
Và trong chức năng của bạn, bạn cần phải lưu trữ khóa bằng cách nào đó:
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);
}
}
Không tối ưu nhưng có thể hoạt động.
Nguồn
2015-05-25 21:00:47
Không, cả hai chủ đề sẽ chờ 'a'. Nó có thể là nếu có phương pháp thứ hai, nơi bạn lần đầu tiên đồng bộ hóa trên 'b' và sau đó trên 'a'. – Stan
Vì vậy, nếu performAction() sẽ sử dụng đối tượng a trong một phương thức được đồng bộ hóa thì sẽ có một Deadlock chẳng hạn? – MrBoolean
Trong trường hợp được cung cấp không kể từ chuỗi 1 sẽ chờ giải phóng đối tượng 'a' cho đến khi kết thúc phương thức – Stan