【发布时间】:2014-02-27 22:36:12
【问题描述】:
我正在尝试弄清楚如何同步对来自不同类的同步列表的读/写访问。
一个小例子:我在一个类ListProvider 中有一个同步列表,我在另一个类Filter 中访问它。顾名思义,该类基于(无效)验证检查isInvalid 执行一些过滤。
filter 方法首先获取列表引用,然后将要删除的条目收集到一个临时列表中,以免遇到并发修改问题,最后从列表中删除条目:
public class Filter {
ListProvider listProvider;
...
public void filter() {
List<String> listProviderList = listProvider.getList();
List<String> entriesToRemove = new ArrayList<>();
// collect
for (String entry : listProviderList)
if (isInvalid(entry)) {
entriesToRemove.add(entry);
}
}
// remove
for (String entry : entriesToRemove) {
listProviderList.remove(entry);
}
}
}
我的问题:如何确保在filter 进行读写时没有其他线程修改列表?
如果是Filter 自己的列表,我会这样做:
synchronized(myList) {
// collect
// remove
}
但在这种情况下,我不确定将什么用作监视器。
【问题讨论】:
-
所有对列表的访问必须同步。因此,如果另一个线程获得该列表,他们还需要在使用它之前对其进行同步。如果您不控制代码,这可能是不可能的。考虑用一些同步包装返回的列表。查看
Collections课程。 -
调用
listProvider.getList()时返回原始列表的副本 -
@hoaz 但是我会丢失 ListProvider#getList 和 ListProvider#setList 之间列表的所有可能更新。原始列表的一致性/正确性是最重要的,我不太关心性能。访问应该简单地发生在 FCFS 的基础上。
-
@SotiriosDelimanolis
Collections类在这里没有任何用处。它只会同步每个单独的访问,但不会确保要删除的项目尚未被另一个线程删除。整个收集无效条目并删除它们的过程必须是原子的。逐个调用同步很少有用。
标签: java multithreading thread-safety synchronized