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

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

在上面的代码中,如果第一个线程尝试获取数据并且队列为空,则我通过wait(0)进入等待状态,直到其他线程添加数据以排队通过notify()从等待状态释放。

现在,我想在队列已满时添加另一个“锁”,并且有人尝试向其中添加更多数据:
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);
}

结果不是我所期望的,我想我死锁了,原因是进程卡住了。

更新

这是我获取数据的方式:
queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];

这就是我添加数据的方式
  queueSize++;
  endPointer = (endPointer + 1) % mqueueSize;
  queue[endPointer] = data;

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

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

最佳答案

为什么会有三个synchronized语句? wait(0)仅释放对this的锁定,因此只需保留该锁并从方法和synchronized中转储synchronized(myLock)即可。

每当您在某个对象上调用wait(在这种情况下,您是在this上调用)时,该对象上的锁都会自动释放,以允许其他线程继续执行。但是,您永远不要在myLock上调用wait(也不应该,因为您已经在this上调用)。该部分是多余的,并导致死锁。

考虑这种情况:本应添加的线程在myLock上获得了锁定,但发现队列已满,因此等待。此等待不会释放对myLock的锁定。另一个线程想要获取数据,但不能进入synchronized块,因为第一个线程没有释放对myLock的锁定。

结论:删除synchronized(myLock)块。

10-06 14:03