编程语言
首页 > 编程语言> > java – 通过制作浅表副本来避免List上的ConcurrentModificationException

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

作者:互联网

我有一个类如下:

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);
    }
}

可以同时修改人员:一个是通过一个线程删除(),另一个是通过getAllPersons()返回的浅复制实例.

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

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

解决方法:

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

您的代码中仍然存在一个小错误 – 要安全地访问本身不是线程安全的成员,您应该在getAllPersons方法上进行同步.

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

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

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

标签:java,list,shallow-copy,concurrentmodification
来源: https://codeday.me/bug/20190613/1236103.html