kenny
kenny

Reputation: 2030

Executing thread "one by one"

There is a singleton class that n threads can access.
Each thread loads the instance of this class and invoke a method from this class in a loop.

I must control the flow of the execution so every thread can invoke the method one and pause, only after all thread invoked the method once the must resume their work. Threads can call method in any order, just all of them have to execute method once before moving the loop.

This what I tried to do:

In thread:

 while ( some condition){
    ObjectType obj = theSingleton.getInstance().getSharedObject();
    obj.SomeMethod(threadID);
   if (obj.waitisneeded())
    synchronized (obj ) {
       obj.wait();
    }
}

what I did in SomeMethod:

public  synchronized void SomeMethod(String threadID) {
 hashMap.put(threadID,true);
 some job here
}

and in waitisneeded:

public  synchronized boolean waitisneeded(){
{

   Iterator iter = hashMap.entrySet().iterator();

   boolean alldone = false;

   while (iter.hasNext()) { 
      Map.Entry me = (Map.Entry) iter.next();
      String key = me.getKey().toString();
      alldone = (Boolean)me.getValue();

      if(!alldone)  {
    return false;
       }
   }

  //set all values to false 
 iter = hashMap.entrySet().iterator();
 while (iter.hasNext()) { 
   Map.Entry me = (Map.Entry) iter.next();
    String key = me.getKey().toString();
   me.setValue(false);      
 }      
 this.notifyAll();
 return true;               

Running this got me unexpected results and deadlocks.

How can I fix it?

Note: I can't change how the thread is created, I can only change those methods!!! (plus the while loop in the thread where wait is)

Upvotes: 2

Views: 981

Answers (2)

GETah
GETah

Reputation: 21409

This is a typical multithreading situation called Rendez-Vous (a french word meaning "appointment"). Basically your N threads will have an appointment and should all wait at a point until all of them reach it. As @Bruno mentioned, you can use a CyclicBarrier object to manage the situation. In case your scenario is run only once then you could also use a CountDownLatch.

Here is how you can achieve this:

static final CountDownLatch rendezVousPoint = new CountDownLacth(numberOfThreads);

//Every thread does the following right before waiting on the rendez vous point
rendezVousPoint.countDown();
rendezVousPoint.await();

In this situation, every thread will block on await() method until the last thread arrives and releases all of them (rendezVousPoint count reaches 0)

Upvotes: 0

Bruno Reis
Bruno Reis

Reputation: 37822

If you know the number of threads, you can use a CyclicBarrier:

static final CyclicBarrier barrier = new CyclicBarrier(numberOfThreads);

Then, at the point in which you want to make all threads wait for the others, you call:

barrier.await();

If there's a thread that has not yet arrived at that line, the thread calling await() will block. Once all the threads arrive there and call await(), they will all resume.

Every time you must build some synchronization mechanism, be sure to check the package java.util.concurrent. There are lots of wonderful classes over there, created by experts. Most of the time you won't need something custom, and if you do, there are some classes in the same package that will make it almost unecessary to use wait/notify directly -- and, believe me, you want to avoid using these methods directly; as you can see, you can very easily get yourself into a deadlock!

Upvotes: 2

Related Questions