我有一个问题。我想我知道答案,但出于某种原因,我更愿意在这里提出要求。
所以这是场景:
我有一个Object,它有一个列表作为字段。然后我有一个方法将列表作为unmodifiableList返回。
Oject类有其他方法可以向列表中添加元素。
因此,让我们设想一个案例,其中一个线程正在迭代不可修改的列表,另一个线程使用Object类方法将元素添加到列表中。
如何使这个线程安全?如果我同步unmodifiableList和列表itselft它会使它线程安全吗?毕竟它们是两个不同的对象,其中unmodifiableList有一个字段,它是裸列表itselft。
答案 0 :(得分:4)
你需要制作"裸体" list synchronized:
private List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>());
但要注意:这只会确保列表内部状态是连贯的。只要迭代列表,就不能阻止在对列表迭代器的两次调用之间对列表进行修改。因此,在这种情况下,什么都不会阻止ConcurrentModificationException发生。为了防止这种情况,您不应该向列表返回任何引用(甚至是间接引用)。列表的所有修改和迭代都应封装在您的类中,并正确同步。
答案 1 :(得分:2)
您可以将原始列表的不可修改克隆返回给调用者。 缺点是呼叫者最终可能会失败。列表的版本。但是,通过这种方式,您可以实现安全的迭代。在并发世界中,可以将最后成功更新的数据返回给调用者。
public List<Thing> getThings() {
List<Thing> copytOfThings = new ArrayList<>();
copyOfThings.addAll(_things); //original list items.
return Collections.unmodifiableList(copyOfThings);
}
答案 2 :(得分:0)
有几种方法可以做到这一点: