I am trying to solve the readers-writers problem with writer preference in Java using multi-threading. The following is a stripped down version of what my code does. Will it work?
public PriorityBlockingQueue pq;
public void foo(){
myClass obj = new myClass();
pq.add(obj);
obj.wait();
//Actual code
}
public void bar(){
pq.remove().notify();
}
Assume that the priority queue pq is empty initially and the constructor of the enclosing class calls the constructor of pq. Also, foo is called first by one thread and then bar by another thread. So when foo is called, it adds obj to the queue and that becomes the front element so that when the remove is called in bar that is the element that is removed. My question is, will "Actual code" be executed? Or am I performing wait() and notify() on two completely different objects? If so, how can I fix it?
解决方案
The main issue I can see with this is that threads can wake up spuriously... so you should always have some data associated with conditions. Also notifyAll() is less likely to result in deadlock... so:
public void foo() {
MyClass obj = new MyClass();
pq.add(obj);
synchronized(obj) {
while (!obj.isDoneBeingProcessed()) {
obj.wait();
}
}
}
public void bar() {
MyClass next = pq.remove();
if (!next) {
return;
}
next.doProcessing();
synchronized(next) {
next.setDone(true);
next.notifyAll();
}
}
Note, though, that this code really doesn't make sense because it essentially serializes the entire computation. It would make more sense if you were to enqueue everything in one thread, while in another thread you did the processing, and then ... only at the end or in another thread attempted to wait on everything. Putting the wait in the producer phase before everything has been produced effectively serializes your entire computation.