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