Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callers block until getFoo() has a value ready?

I have a Java Thread which exposes a property which other threads want to access:

class MyThread extends Thread {
   private Foo foo;
   ...
   Foo getFoo() {
     return foo;
   }
   ...
   public void run() { 
     ...
     foo = makeTheFoo();
     ...
   }
}

The problem is that it takes some short time from the time this runs until foo is available. Callers may call getFoo() before this and get a null. I'd rather they simply block, wait, and get the value once initialization has occurred. (foo is never changed afterwards.) It will be a matter of milliseconds until it's ready, so I'm comfortable with this approach.

Now, I can make this happen with wait() and notifyAll() and there's a 95% chance I'll do it right. But I'm wondering how you all would do it; is there a primitive in java.util.concurrent that would do this, that I've missed?

Or, how would you structure it? Yes, make foo volatile. Yes, synchronize on an internal lock Object and put the check in a while loop until it's not null. Am I missing anything?

like image 312
Sean Owen Avatar asked May 14 '10 19:05

Sean Owen


2 Answers

If foo is initialized only one time, a CountDownLatch is a great fit.

class MyThread extends Thread {

  private final CountDownLatch latch = new CountDownLatch(1);

  ...

  Foo getFoo() throws InterruptedException
  {
    latch.await(); /* Or use overload with timeout parameter. */
    return foo;
  }

  @Override
  public void run() {
    foo = makeTheFoo()
    latch.countDown();
  }

}

Latches provide the same visibility behavior as the volatile keyword, meaning that reading threads will see the value of foo assigned by the thread, even though foo isn't declared volatile.

like image 140
erickson Avatar answered Nov 13 '22 03:11

erickson


In general notify() and notifyAll() are the methods you want. notify() is dangerous if only one item is creating the Foo and many threads might wait for it. But I think there are some other issues here.

I wouldn't make the Thread the place to store the Foo. Doing so means you have to keep a thread around after Foo is created. Why not make another object to store the Foo, and have the creating thread write to it?

Then I would have getFoo() test foo and only wait if it was non-null (don't forget to synchronize it with itself and with the foo setter).

like image 3
DJClayworth Avatar answered Nov 13 '22 02:11

DJClayworth