通过进行浅表复制来避免List上的ConcurrentModificationException [英] Avoiding ConcurrentModificationException on List by making a shallow copy

查看:153
本文介绍了通过进行浅表复制来避免List上的ConcurrentModificationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似于以下的课程:

I have a class like the following:

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

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

persons may be modified concurrently: one is via remove() by one thread and two via the shallow copied instance returned by getAllPersons().

我已经在多线程环境中测试了上述情况,以查看是否可以通过在调用getAllPersons()时返回浅表副本来避免ConcurrentModificationException.它似乎有效.我从未见过ConcurrentModificationException.

I have tested the above scenario in a multithreaded environment to see if I can avoid ConcurrentModificationException by returning a shallow copy when getAllPersons() is called. It seemed to work. I have never once encountered a ConcurrentModificationException.

在这种情况下,为什么仅制作persons的浅表副本会避免ConcurrentModificationException?

Why, in this case, does making only a shallow copy of persons avoid a ConcurrentModificationException?

推荐答案

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

A ConcurrentModificationException is thrown when a collection changes in a manner which invalidates open iterators. This usually happens when a collection which is not thread safe is accessed by multiple threads (although this is not the only cause)

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

There is still a small error in your code - to safely access a member which is not itself thread safe, you should synchronize on the getAllPersons method.

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

Assuming that is fixed -- because you are returning a copy, the collection itself cannot be modified by other callers (each gets their own copy). That means that you can never get a ConcurrentModificationException.

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

Note that this does not protect you against thread safety issues with your Person class, only the collections themselves. If Person is immutable, you should be OK.

在这种情况下,更好的解决方案是直接使用 CopyOnWriteArrayList ,它实现了类似的语义,但仅在您实际写入列表时才进行复制-并非每次读取时都复制.

In this case, a better solution would be to directly use a CopyOnWriteArrayList which implements similar semantics, but only copies when you actually write to the list - not every time you read from it.

这篇关于通过进行浅表复制来避免List上的ConcurrentModificationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆