单线程更新、线程池只读的成员变量是否需声明为volatile?
成员变量是否需要声明为volatile的问题
若成员变量由一个线程更新,之后由线程池中的其他线程读取(不更新),该成员变量是否需要声明为volatile?
用于说明问题的示例代码:一个使用白名单引用的过滤器,白名单在并行读取前被更新:
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 } }
我了解volatile能保证所有线程“看到”当前值,但在此示例中,positiveNameList是否必须声明为volatile?
我的直觉认为不需要。但从线程角度看,positiveNameList由调用线程更新,之后被ForkJoinPool.commonPool中的线程读取,这些线程可能在之前执行getFiltered()方法时“看到”该变量的旧引用。
无论结论如何,我也想了解该行为在JLS内存模型规范中的哪部分有描述。
内容的提问来源于stack exchange,提问作者SebastianBrandt
相关产品推荐
相关产品推荐

