[concurrency-interest] Future Get/Done Race Condition

Sam Berlin sberlin at gmail.com
Tue Jan 30 17:33:53 EST 2007


Hi Folks,

We recently started running our tests on a faster multi-processor
machine and ran into a few race conditions, one of which we're unsure
of how to fix.  What we're experiencing is that a Thread that has
created a future and calls 'get' on it can retrieve the result before
the future has 'done' called on itself.  This leads to more code being
able to act before the finished-state of the future has cleaned itself
up.

The reason this is a problem is that we want to limit the number of
outgoing pings sent to a host.  When Manager.ping(Host) is called, it
synchronizes on a map and checks to see if there's an outstanding
future for that host, and if so, returns it.  Otherwise (if there's no
outstanding future), it creates one, adds it to the map, submits it to
an executor service, and returns it.  When the future is finished,
it's overridden done method synchronizes on the map and removes
itself.

The end result is the following code sometimes works & sometimes doesn't:

---
  // Setup response scenario, send ping & assert response
  Future<PingResult> future = pingManager.ping(host);
  PingResult result = future.get();
  // check response assertions
  // Change scenario so no response is sent..
  try {
      pingManager.ping(host).get();
      fail("shouldn't have gotten a response!");
      // Note: this fails occasionally because the above
      // future's done method isn't called yet (which removes
      // the outstanding future), so the pingManager
      // is returning the same Future as above.
  } catch(ExcecutionException expected) {}
---

We can easily add a small sleep, or a Thread.yield() to make sure
other threads process (and the done() is called), but I'm wondering if
there's any better way.

Thanks very much for any ideas.

Sam


More information about the Concurrency-interest mailing list