2015-05-25 15 views
6
public void function(object a, object b){ 
    synchronized(a){ 
     synchronized (b){ 
      a.performAction(b); 
      b.performAction(a); 
     } 
    } 
} 

Bế tắc bằng 2 chủ đề? Cảm ơn câu trả lời!Có phải bế tắc có thể xảy ra trong phương pháp này không? Làm thế nào tôi có thể ngăn chặn nó?

+0

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

+0

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

+0

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

Trả lời

11

Chắc chắn,

Giả sử chúng ta có hai đối tượng,

Object one = ...; 
Object two = ...; 

Và giả sử thread 1 cuộc gọi:

function(one, two); 

Trong khi chủ đề 2 cuộc gọi:

function(two, one); 

Trong chủ đề 1, a == oneb == two, nhưng trong chuỗi 2, a == twob == one.

Vì vậy, trong khi chuỗi 1 đang lấy khóa trên đối tượng một, chuỗi 2 có thể lấy khóa trên đối tượng hai. Sau đó, khi mỗi chủ đề cố gắng thực hiện bước tiếp theo, chúng sẽ bị bế tắc.

+0

Bạn có thể sửa lỗi đó bằng cách khóa lệnh asc/desc hashcode. Dù sao nó không tốt đẹp. – Aitch

2

Để 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.

Các vấn đề liên quan