首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待/通知死锁

等待/通知死锁
EN

Stack Overflow用户
提问于 2011-12-15 11:41:26
回答 5查看 348关注 0票数 1

我在"Add“和"Get”方法中有一个带有阻塞机制的队列,其中第一个线程添加数据,第二个线程获取数据。

代码语言:javascript
复制
public synchronized MyObj getData() {               
    synchronized (myLock) {
        synchronized (this) {
            if (isEmpty()) {                
                wait(0);                    
            }
        }       


        return getData();           
    }
}

public synchronized void addData(MyObj data) {
    if (!isFull()) {
        putData(data);
        synchronized (this) {
            notify();
        }
    }
}

在上面的代码中,如果第一个线程试图获取数据,而队列是空的,则我通过等待(0)输入等待,直到其他线程添加数据来排队等待data ()的发布。

现在,当队列已满时,我想添加另一个“锁”,并且有人试图向队列中添加更多数据:

代码语言:javascript
复制
public synchronized MyObj getData() {               
    synchronized (myLock) {
        synchronized (this) {
            if (isEmpty()) {                
                wait(0);                    
            }
        }       

        synchronized (this) {
            notify();
        }
        return getData();           
    }
}

public synchronized void addData(MyObj data) {
    synchronized (myLock) {
        synchronized (this) {
            if (isFull()) {
                wait(0);
            }
        }
    }

    synchronized (this) {
        notify();
        }
        PutData(data);
}

结果不是我所期望的,我想我得到了一个死锁,因为过程是卡住了。

更新

我就是这样得到数据的:

代码语言:javascript
复制
queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];

我就是这样添加数据的

代码语言:javascript
复制
  queueSize++;
  endPointer = (endPointer + 1) % mqueueSize;
  queue[endPointer] = data;

public synchronized boolean isEmpty() {
        return queueSize== 0;
    }

    public synchronized boolean isFull() {
        return queueSize== mqueueSize;
    }
EN

回答 5

Stack Overflow用户

发布于 2011-12-15 12:35:02

为什么有三条synchronized语句?wait(0)只释放this上的锁,所以只需保留该锁并从方法和synchronized(myLock)中转储synchronized

每当您调用某个对象(在本例中是对this的调用)时,该对象上的锁将自动释放,以允许其他线程继续执行。但是您永远不会调用myLock (而且您也不应该这样做,因为您已经在调用this )。该部分是多余的,并导致死锁。

考虑一下这个场景:应该添加的线程接受myLock上的锁,但发现队列已满,所以它等待。此等待不会释放myLock上的锁。另一个线程希望获取数据,但不能进入synchronized块,因为第一个线程没有释放myLock上的锁。

结论:去除synchronized(myLock)阻滞。

票数 3
EN

Stack Overflow用户

发布于 2011-12-15 11:45:08

为什么你不看看java.util.BlockingQueue。在你的情况下它可能是有用的。

特别是看看java.util.LinkedBlockingQueue,如果在构造函数中指定队列的容量,那么队列就会阻塞。

票数 1
EN

Stack Overflow用户

发布于 2011-12-15 11:47:07

从方法签名中删除synchronized关键字,因为这意味着您持有整个方法调用的this监视器-- synchronized(this)块只是多余的。

编辑:

...Then在myLock上调用、等待和通知,而不是this。完全忘记在this上同步的问题。这是因为在等待(当前代码中的this )时,没有释放myLock锁,因此其他线程无法到达notify()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8519529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档