通过制作浅表副本来避免List上的ConcurrentModificationException

His*_*His 4 java list shallow-copy concurrentmodification

我有一个类如下:

class Test
{
    private LinkedList<Person> persons = new LinkedList<Person>;

    public synchronized void remove(Person person)
    {
        persons.remove(person);
    }

    public List<Person> getAllPersons()
    {
        // Clients may iterate over the copy returned and modify the structure.
        return new ArrayList<Person>(persons);
    }
}
Run Code Online (Sandbox Code Playgroud)

persons可以同时修改:一个通过remove()一个线程,两个通过返回的浅复制实例getAllPersons().

我已经在多线程环境中测试了上述场景,看看我是否可以ConcurrentModificationException通过在getAllPersons()调用时返回浅拷贝来避免.它似乎工作.我从来没有遇到过ConcurrentModificationException.

在这种情况下,为什么只做一个浅的副本persons避免ConcurrentModificationException

Ste*_*ker 6

当集合以使打开的迭代器无效的方式更改时,将引发ConcurrentModificationException.当多个线程访问非线程安全的集合时,通常会发生这种情况(尽管这不是唯一的原因)

您的代码中仍然存在一个小错误 - 要安全地访问本身不是线程安全的成员,您应该synchronize使用getAllPersons方法.

假设这是固定的 - 因为你要返回一个副本,集合本身不能被其他调用者修改(每个调用者都有自己的副本).这意味着您永远不会得到ConcurrentModificationException.

请注意,这不会保护您免受类的线程安全问题Person,只保护集合本身.如果Person是不可变的,你应该没问题.

在这种情况下,更好的解决方案是直接使用实现类似语义的CopyOnWriteArrayList,但只有在实际写入列表时才复制 - 而不是每次从中读取时.