Reputation: 49
Is it safe to check a field modified by a task executed in a Future<?>
after successfully calling future.get()
?
(Is it guaranteed to be finished setting the value, and I'm seeing the new value?)
I would check the field on the same thread as calling the future.get()
.
Or should I only use the return value of future.get()
and should not expect this to work like this?
Example:
class MyData {
private int a;
public void setA(int a) { this.a = a; }
public int getA() { return a; }
}
public class MainClass {
public static void main(String[] args) {
final Executor executor = Executors.newFixedThreadPool(15);
final List<MyData> objects = Arrays.asList(new MyData(), new MyData() /* ... */);
final Future<Void> future1 = CompletableFuture.supplyAsync(() -> { objects.get(0).setA(1); return null; }, executor);
final Future<Void> future2 = CompletableFuture.supplyAsync(() -> { objects.get(1).setA(2); return null; }, executor);
/* ... */
a.get();
b.get();
/* ... */
// Is it safe here to check the `a` field of the objects?
assert objects.get(0).getA() == 1;
assert objects.get(1).getA() == 2;
}
}
Upvotes: 0
Views: 139
Reputation: 280181
The javadoc of Future
states
Memory consistency effects: Actions taken by the asynchronous computation happen-before actions following the corresponding
Future.get()
in another thread.
Since get
will only return when the corresponding computation completes (the setA
invocation and return
), that computation is visible through the happen-before relationship to any code after the call to get
. Your call to getA
occurs after the Future#get
, so it'll see the results of the setA
which happened before it.
Upvotes: 1
Reputation: 116
As the documentation of Future#get()
says:
Waits if necessary for the computation to complete, and then retrieves its result.
So it is completely safe to do the assertions once calling the Future.get()
method since the values will be resolved by then.
Upvotes: 0