线程安全读取并实例化列表

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()方法完全设置,列表没有其他变化。

ysh*_*vit 6

是的,你所拥有的将会起作用。

\n

如果您不需要协调列表的刷新与任何其他状态,您也可以使用final AtomicReference<List<Foo>>,甚至使用volatile List<Foo>。在任何一种情况下,您都不需要将您的方法标记为synchronized: BothAtomicReferencevolatile具有交叉引用内存保证,只要分配/设置到该字段的对象在分配后不会发生变化。

\n

为了使其发挥作用,至关重要的是List不发生变异,并且它的任何一个Foo都不会发生变化(除非它们是线程安全的)。如果是我,我会将列表包装在一个Collections.unmodifiableList或一些其他不可修改的列表中,例如List.copyOf,并添加注释,其效果是“为了线程安全,这需要不可修改”,以便其他人以后不会更改却没有意识到他们正在破坏什么。(很难编写一个单元测试来检测错误 \xe2\x80\x94 ,更有可能的是,你会意外地在产品中遇到错误。)

\n