在监视器的上下文中,被调用notify()唤醒后被阻塞的线程在哪里继续执行?

时间:2017-04-12 19:05:25

标签: java synchronization monitors

它在调用wait()之后是否会立即继续执行?它是从服务方法的开头一直开始的吗?

Stephen Hartley的并发编程的一段话:Java编程语言对这个问题有这个说法,我不确定我是否完全理解:

  

此通知方案无法在同步监视器服务方法的中间等待信号,然后在接收到信号后继续在监视器服务方法内执行。

它所指的通知方案是使用通知对象解决读者和写作者问题的实现。

以下是该解决方案的代码片段(我只展示与读者相关的方法):

private int numReaders = 0;
private boolean isWriting = false;
private Vector waitingReaders = new Vector();
private Vector waitingWriters = new Vector();

public void startRead(int i) {
    Object convey = new Object();
    synchronized (convey) {
        if (cannotReadNow(convey))
            try { convey.wait(); }
            catch (InterruptedException e) {}
    }
}

private synchronized boolean cannotReadNow(Object convey) {
    boolean status;
    if (isWriting || waitingWriters.size() > 0) {
        waitingReaders.addElement(convey); status = true;
    } else {
        numReaders++; status = false;
    }
    return status;
}

public synchronized void endRead(int i) {
    numReaders--;
    if (numReaders == 0 && waitingWriters.size() > 0) {
        synchronized (waitingWriters.elementAt(0)) {
            waitingWriters.elementAt(0).notify();
        }
        waitingWriters.removeElementAt(0);
        isWriting = true;
    }
}

我很困惑的原因是上面的引用似乎与同一本书的代码示例中显示的编程实践相矛盾。

例如,这是使用普通监视器的读者和写作者解决方案的代码片段,没有通知对象

public synchronized void startRead(int i) {
    long readerArrivalTime = 0;
    if (numWaitingWriters > 0 || numWriters > 0) {
        numWaitingWriters++;
        readerArrivalTime = age();
        while (readerArrivalTime >= startWritingReadersTime)
            try {wait();}
            catch (InterruptedException e) {}
        numWaitingReaders--;
    }
    numReaders++;
}

如果一个线程无法继续执行被wait()调用阻塞的位置,为什么还有一个while循环来检查条件?如果每个被阻塞然后通过调用startRead()重新获得进入监视器的线程必须从该方法的开头开始,正如上面的引用似乎建议的那样,if语句就不足以满足检查条件?

此外,这一点如何解释下一篇引文,在上面引用之后的书中紧接着:

  

为避免死锁,在等待通知对象内部之前,线程必须使用return语句保留synchronized方法。

1 个答案:

答案 0 :(得分:0)

如果我理解这个问题......试试这个:

public synchronized void startRead(int i) {
    long readerArrivalTime = 0;
    if (numWaitingWriters > 0 || numWriters > 0) {
        numWaitingWriters++;
        readerArrivalTime = age();
        while (readerArrivalTime >= startWritingReadersTime)
            try {wait();}
            catch (InterruptedException e) {}
        numWaitingReaders--;
    }
    numReaders++;
}
public synchronized void endRead(int i) {
    numReaders--;
    if (numReaders == 0 && waitingWriters.size() > 0) {
        notify();
        waitingWriters.removeElementAt(0);
        isWriting = true;
    }
}

concreteObject.wait / notify / notifyAll方法只能从synchronized(concreteObject)块中调用。如果你调用他们没有concreteObject(只是wait()或notify()),它与this.wait()或this.notify()相同。

同步非静态方法与synchronized(this)块相同。