eri*_*iee 5 java concurrency list thread-safety
我需要实现如下列表:
private List<Foo> list = new ArrayList<>();
public synchronized Foo getFoo(Condition condition) {
// loop the list and get a foo that meets the condition
for (Foo foo: list) {
if(condition.check(foo)) {
return foo;
}
}
return null;
}
public synchronized void refresh() {
list = new ArrayList<>(fetchFromDB());
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来避免同步方法以使读取和实例化线程安全?我认为 CopyOnWriteArrayList 在这里没有帮助,因为同一个列表上没有变异操作,而且每次我们只是创建一个新列表。我对吗?
更新:澄清一下,该列表只能通过refresh()方法完全设置,列表没有其他变化。
是的,你所拥有的将会起作用。
\n如果您不需要协调列表的刷新与任何其他状态,您也可以使用final AtomicReference<List<Foo>>,甚至使用volatile List<Foo>。在任何一种情况下,您都不需要将您的方法标记为synchronized: BothAtomicReference并volatile具有交叉引用内存保证,只要分配/设置到该字段的对象在分配后不会发生变化。
为了使其发挥作用,至关重要的是List不发生变异,并且它的任何一个Foo都不会发生变化(除非它们是线程安全的)。如果是我,我会将列表包装在一个Collections.unmodifiableList或一些其他不可修改的列表中,例如List.copyOf,并添加注释,其效果是“为了线程安全,这需要不可修改”,以便其他人以后不会更改却没有意识到他们正在破坏什么。(很难编写一个单元测试来检测错误 \xe2\x80\x94 ,更有可能的是,你会意外地在产品中遇到错误。)