[concurrency-interest] Proper workaround for FutureTask.set()/get() race (CR 7132378)

Doug Lea dl at cs.oswego.edu
Sat Apr 21 10:51:24 EDT 2012


On 04/20/12 04:29, Aleksey Shipilev wrote:
> Hi guys,
>
> I'm trying to workaround the FutureTask race described in CR 7132378:
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7132378
>
> I do realize the fix is already there in Doug's code, but both waiting
> for JDK update or bootclasspath-ing jsr166.jar is not an option for this
> particular case I'm dealing with.

Although it would seem that if you could add SettableFuture, you
might as well just take/adapt the updated FutureTask class instead?
Even if you have to cripple it a bit by using AtomicXFieldUpdaters
instead of direct CAS calls, it is probably a better option.
If not, your workaround seems OK though.

(BTW, one moral of that CR is that whenever you don't explicitly
disallow an unintended usage, it will eventually  end up as a
bug report :-)


-Doug


>
> Hence, my question is: can this code be considered a proper workaround?
>
> /**
>   * Specialized form of future allowing to set the result.
>   *
>   * @param<V>
>   */
> public class SettableFuture<V>  extends FutureTask<V>  {
>
>      /**
>       * Implementation notes:
>       *
>       * This implementation also accounts for known bug in FutureTask:
>       * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7132378
>       *
>       * We compensate for possible race by making sure set() had
>       * completed before returning from get(). Since get() is
>       * blocking operation, we first wait without any synchronization,
>       * and then do get() again synchronizing with set() to make sure
>       * set() had indeed completed.
>       *
>       * This bails out earlier on exception or if the timeout had
>       * expired.
>       */
>
>      /**
>       * Dummy callable so that underlying implementation
>       * will not complain.
>       */
>      private static final Callable DUMMY = new Callable() {
>          @Override
>          public Object call() throws Exception {
>              throw new IllegalStateException("Trying to read from dummy
> callable in SettableFuture");
>          }
>      };
>
>      public SettableFuture() {
>          super(DUMMY);
>      }
>
>      @Override
>      public void set(V v) {
>          synchronized (this) {
>              super.set(v);
>          }
>      }
>
>      @Override
>      protected void setException(Throwable t) {
>          synchronized (this) {
>              super.setException(t);
>          }
>      }
>
>      @Override
>      public V get() throws InterruptedException, ExecutionException {
>          super.get();
>          synchronized (this) {
>              return super.get();
>          }
>      }
>
>      @Override
>      public V get(long timeout, TimeUnit unit) throws
> InterruptedException, ExecutionException, TimeoutException {
>          super.get(timeout, unit);
>          synchronized (this) {
>              return super.get();
>          }
>      }
> }
>
> Thanks,
> Aleksey.
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>



More information about the Concurrency-interest mailing list