2015-05-18 69 views
-1

請幫助我。此代碼可能被阻止在哪裏? 我認爲它不應該阻止。該線程,該getItem等待, 細節出現在存儲中,並通知任何人,如果它從存儲獲取任何項目。 putItem中的線程,當 它將任何細節放入存儲並等待它已滿。這樣對嗎? 我認爲不會,因爲出現死鎖 對不起我的英文。這不是我的母語。同步塊。僵局。 Java

public class Storage<E> { 

ArrayList<E> details; 
private Integer limit; //Storage Capacity 
final MonitorObject expectItemObject; //objects for synchronization 
final MonitorObject expectPlaceObject; 

public Storage(Integer limit) 
{ 
    this.limit = limit; 
    expectItemObject = new MonitorObject(); 
    expectPlaceObject = new MonitorObject(); 
    details = new ArrayList<>(limit); 
} 
public Integer getSize() 
{ 
    int detNo=0; 
    synchronized (expectPlaceObject) 
    { 
     synchronized (expectItemObject) { 
      detNo = details.size(); 
     } 
    } 
    return detNo; 
} 
public void putItem(E e) throws InterruptedException 
{ 
    synchronized (expectPlaceObject) 
    { 
     while (getSize().equals(limit)) { //ensure that we have a place 
      expectPlaceObject.wait(); //sleep if storage is full 
     } 
     synchronized (expectItemObject) { //there is no trouble in inners synchronized, as the second is not blocking. 
      details.add(e); 
      expectItemObject.notify(); //if anybody,who expect item, sleep, awake him. 

     } 

    } 

} 
public E getItem() throws InterruptedException 
{ 
    E detail; 
    synchronized (expectItemObject) 
    { 
     while (getSize() == 0) { 
      expectItemObject.wait(); //sleep if storage is empty 
     } 
     synchronized (expectPlaceObject) { 
      detail= details.remove(0); 
      expectPlaceObject.notify(); //if anybody,who expect place sleep, awake him. 
     } 

    } 
    return detail; 
} 
} 
+0

邊注:一個癥結與鎖定;人類在預測會發生什麼時非常糟糕。我讀了你的代碼,並檢查了「他是否總是以相同的順序請求鎖?」,並忽略了你正在做的。有時候這些東西很容易,但很多時候卻不是。然後,創建一個Java轉儲並分析它的速度就快很多了。所以我的建議是:學習如何做到這一點;它可以爲你節省大量的時間。 – GhostCat

回答

2

putItemgetItem要同步兩個不同的OBJETS,expectPlaceObjectexpectItemObject

問題是,您在兩種方法中以不同的順序同步它們。什麼都可能發生如下:

  1. 線程A調用putItem和鎖expectedItemObject
  2. 同時線程B調用getItem和鎖expectedPlaceObject
  3. 接下來兩個線程要鎖定另一個線程已經鎖住了一個對象,導致死鎖。

調查死鎖的一個好方法是使用jstack來進行進程的線程轉儲。輸出將列出您的死鎖。

+0

謝謝!我應該猜測。 – Artem

1

嘗試使用這種改變你的getSize()方法:

public Integer getSize() { 
    return details.size(); 
}