【问题标题】:Syncronized blocks. DeadLock. Java同步块。僵局。爪哇
【发布时间】:2015-05-18 14:24:18
【问题描述】:

请帮助我。此代码可能会在哪里被阻止? 我认为它不应该阻塞。线程,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;
}
}

【问题讨论】:

  • 旁注:一个症结在于锁定;人类非常不善于预测会发生什么。我阅读了您的代码并检查了“他是否总是以相同的顺序请求锁定”......并且忽略了您正在这样做。有时这些事情真的很容易,但很多时候并非如此。然后创建一个 java 转储并分析它会快得多。所以我的建议是:学习如何做到这一点;它可以在未来为您节省大量时间。

标签: java deadlock synchronized


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多