同步块。僵局。 Java

Syncronized blocks. DeadLock. Java

请帮帮我。此代码可能在哪里被阻止? 我认为它不应该阻止。 getItem 等待的线程, 详细信息出现在存储中,并在从存储中获取任何项目时通知任何人。 putItem 通知的线程,何时 它会将任何详细信息放入存储中,并等待它是否已满。这样对吗? 我认为不,因为出现僵局 对不起我的英语。这不是我的母语。

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

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

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

  1. 线程 A 调用 putItem 并锁定 expectedItemObject
  2. 同时线程 B 调用 getItem 并锁定 expectedPlaceObject
  3. 接下来两个线程都想锁定另一个线程已经锁定的对象,这会导致死锁。

调查死锁的一个好方法是使用 jstack 获取进程的线程转储。输出将列出您的死锁。

尝试用这个改变你的 getSize() 方法:

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