在监视器的上下文中,被阻塞的线程在被notify()调用唤醒后在何处继续执行?
它是否在调用wait()
后立即继续执行?它是从服务方法的开始就开始的吗
斯蒂芬·哈特利(Stephen Hartley)的《并发编程:Java编程语言》(Concurrent Programming:Java Programming Language)中有一段话是关于这个问题的,我不确定我是否完全理解:
It is not possible with this notification scheme to wait in the middle of a synchronized monitor service method for a signal and then continue executing inside the monitor service method at that point after receiving the signal.
它所指的通知方案是使用通知对象解决读写器问题的实现
下面是该解决方案的代码片段(我只展示与读者相关的方法):
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语句不足以检查条件吗
此外,这些如何解释书中紧接着上述引用的下一句引用:
To avoid deadlock, the thread must leave the synchronized method with a return statement before waiting inside the notification object.
# 1 楼答案
如果我理解这个问题。。。试试这个:
具体对象。只能从synchronized(concreteObject)块调用wait/notify/notifyAll方法。如果在不使用concreteObject的情况下调用它们的函数(只需wait()或notify()),则与此相同。等等或者这个。通知()
同步的非静态方法与同步(this)块相同