Reputation: 459
If a member variable is updated by one thread and later read (not updated) by other treads from a thread pool, does that member variable needs to be declared as volatile?
Made-up code to illustrate the question: A filter that uses a positive-list reference that is updated before used (read) in parallel:
public class PetFilter {
private final PositiveListProvider positiveNameListProvider;
private Set<String> positiveNameList; // Should be volatile?
public PetFilter(PositiveListProvider positiveNameListProvider) {
this.positiveNameListProvider = positiveNameListProvider;
}
public List<Pet> getFiltered(List<Pet> unfiltered) {
// assume that getPositiveList returns a new reference
this.positiveNameList = positiveNameListProvider.getPositiveList(); // written by caller thread
return unfiltered.stream().parallel().filter(this::accept).toList();
}
private boolean accept(Pet candidate) {
return positiveNameList.contains(candidate.getName()); // read by threads form ForkJoinPool.commonPool
}
}
I'm aware that volatile guarantees that all threads "see" the current value, but is it required for positiveNameList in this example?
My gut tells me that positiveNameList does not need to be volatile.
But viewed from the threading perspective, positiveNameList is updated by the caller thread and then read by threads from the ForkJoinPool.commonPool which might have "seen" an older reference of PositiveListProvider in earlier executions of the getFiltered() method.
Either way, I'd also be interested in where in the JLS spec for the memory model the the behavior is described.
Upvotes: 1
Views: 74