是否可能在一个线程中的wait()之前调用另一个线程中的notify()? 它发生在我身上。
客户端从目标请求值并等待结果变量RV。 如果目标是客户端本身,我使用正确的结果更新RV,并在另一个线程中调用RV上的notify()。
class EMU {
ResultVar RV;
Address my_address;
ResultVar findValue(String key) {
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV) {
RV.wait();
}
return RV;
}
Runnable Server = new Runnable() {
public void run() {
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0) {
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
RV.notify();
}
}
}
};
}
问题是在请求者自己完成所有“网络”(上例中的sendReqest)之前,结果会在结果变量中更新。当请求者线程现在调用wait()时,程序不会继续,因为已经调用了notify。
我们如何防止它?
答案 0 :(得分:7)
在等待之前检查一些标志(在循环中),请参阅教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
答案 1 :(得分:5)
在没有被另一个帖子notify
编辑的对象上调用wait
时,没有任何阻止。
听起来你想要的只是在某些条件成立时等待。例如:
synchronized (results) {
while (!results.hasResults()) {
// no results yet; wait for them
try {
results.wait();
} catch (InterruptedException ie) { /* ignore */ }
}
}
答案 2 :(得分:2)
我强烈建议不要重新发明轮子。
Java Future接口专为可能只在以后到达的结果而设计,FutureTask类实现此接口。
让第一个线程获得对Future的访问权并获得第二个线程来运行FutureTask,并为您处理所有这些内容。您还可以免费获得超时支持。
答案 3 :(得分:0)
在转到wait()之前使用某些条件并确保条件是线程安全的:)
class EMU{
ResultVar RV;
Address my_address;
volatile boolean condition = true;
ResultVar findValue(String key){
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV){
while(condition == true)
{
RV.wait();
}
}
return RV;
}
Runnable Server = new Runnable(){
public void run(){
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0){
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
condition = false;
RV.notify();
}
}
}
};
答案 4 :(得分:0)
让我首先将代码分解为可重复的最低代码:
public static void main(String[] args) throws Exception {
Object RV = new Object();
new Thread() {
@Override
public void run() {
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
RV.wait();
}
}
理论上该方法将永远不会结束,并且程序也永远不会退出。如果这是一个僵局,那将是一个争执。
我的解决方案是创建第二个锁:
public static void main(String[] args) throws Exception {
Object RV = new Object();
Object lock = new Object();
new Thread() {
@Override
public void run() {
synchronized (lock) {
lock.wait();
}
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
synchronized (lock) {
lock.notify();
}
RV.wait();
}
}
让我们检查主线程等待一秒钟时线程在做什么:
synchronized(lock)
块。synchronized(lock)
块。程序结束。