Duplicate :
|
|
Relates :
|
|
Relates :
|
This issue came up on the jdk7u-dev mailing list, but is applicable to JDK8 too. http://mail.openjdk.java.net/pipermail/jdk7u-dev/2012-January/001439.html Race explanation: 1. When FutureTask.run() is not used, and only FutureTask.set() is used, FutureTask.set() will race with FutureTask.get(). The race is evidenced by the initial call to FutureTask.get() returning the unassigned null value just before it should have seen the assigned value. A second call to FutureTask.get() will see the proper value. 2. Because FutureTask.run() is not used, Sync.runner is always null, and therefore Sync.acquireSharedInterruptibly(), the guard in Sync.innerGet(), could take the fast path when it calls Sync.innerIsDone(). 3. Over in Sync.innerSet(), the call to Sync.releaseShared(), sets Sync.runner to null, which in the case of never setting runner to begin with, is too late to make Sync.acquireSharedInterruptibly() cause Sync.innerGet() take a slower path. 4. Hence, Sync.innerGet() returns after RAN state is set, but it can return just before Sync.innerSet() sets the value. To repeat, if a client uses FutureTask as an implementation of Future instead of Runnable, this race will happen. If the client uses it as an implementation of Runnable, all seems to be well.
|