同步块。僵局。 Java的

时间:2015-05-18 14:24:18

标签: java deadlock synchronized

请帮帮我。这段代码可能会被阻止在哪里? 我认为它不应该阻止。 getItem等待的线程, 详细信息显示在存储中,如果从存储中获取任何项目,则通知任何人。 putItem notfiy的线程,何时 它将任何细节放入存储中并等待它已满。这样对吗? 我认为不,因为死锁出现了 抱歉我的英语。这不是我的母语。

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;
}
}

2 个答案:

答案 0 :(得分:2)

putItemgetItem您正在同步两个不同的对象,expectPlaceObjectexpectItemObject

问题是您在两种方法中以不同的顺序同步它们。可能发生的事情如下:

  1. 主题A调用putItem并锁定expectedItemObject
  2. 同时,线程B调用getItem并锁定expectedPlaceObject
  3. 接下来两个线程都希望锁定另一个线程已经锁定的对象,这会导致死锁。
  4. 调查死锁的一个好方法是使用jstack来获取进程的线程转储。输出将列出您的死锁。

答案 1 :(得分:1)

尝试使用以下方法更改getSize()方法:

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