views:

29

answers:

1

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<myClass> 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?

A: 

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.

Michael Aaron Safyan
Just assume one thread of each for simplicity. This is more of a question of being able to wait on an object after adding it into a priority queue so that it can be removed later on and notified.
Meher
My problem is actually a large one. I have two priority queues one for readers and one for writers. There are certain policies for allowing readers and writers in at any certain point. Each priority queue consists of request objects (each object consists of only one member int priority). Just before doing a requestobject.wait() (say because there are readers or a writer already using the resource) I wish to add the request object to the priority queue so that I can leave the request to be notified by a last-reader or writer thread later on. I get Illegal Monitor State Exception.
Meher
This appears to be a duplicated question... http://stackoverflow.com/questions/3930152/java-priorityqueue-wait/3939621#3939621
andersoj
@Michael Aaron Safyan: My code was giving me an error because I hadn't used a synchronize block on the right object. I had to read up on synchronize and then only could understand why it is used. Thanks.
Meher