private static final ExecutorService ES = Executors.newWorkStealingPool();
public Future<List<String>> isThisSafe() {
List<String> a = new ArrayList<>();
a.add("a");
List<String> b = new ArrayList<>();
b.add("b");
return ES.submit(() -> {
a.addAll(b);
return a;
});
}
I'll say that thread X is the one that calls isThisSafe(). Thread Y runs the Callable submitted to the ExecutorService.
Right now, I think this works.
✓ The two ArrayLists are never modified by X after being published to Y
✓ ArrayList 'a' is modified by thread Y, but X does not hold a reference to 'a'.. the returned reference to 'a' would be considered 'new' and so X will pull this from MM.
But is there a problem with my second point? Maybe I misunderstand the memory model.
The thread X safely publishes the object a to thread Y and does not do any modification until Y succeeds. So the object a is safely published from thread X to thread Y.
Moreover, All actions in a thread happen-before any other thread successfully returns from a Future.get() on that thread. Upon returning from Future.get() thread X can see all the changes made by thread Y to the object a.
So according to our thread safety analysis, we can conclude that this code is thread safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With