Java 理解和解决ConcurrentModificationException

Java 理解和解决ConcurrentModificationException,java,concurrentmodification,Java,Concurrentmodification,我正在处理一段遗留代码中的间歇性、难以重现的ConcurrentModificationException: class LegacyCode { private final WeakHashMap<A, B> mItems = new WeakHashMap<A, B>(); public void someWork() { final List<A> copy = new LinkedList<A>();

我正在处理一段遗留代码中的间歇性、难以重现的
ConcurrentModificationException

class LegacyCode {
    private final WeakHashMap<A, B> mItems = new WeakHashMap<A, B>();

    public void someWork() {
        final List<A> copy = new LinkedList<A>();

        for (final A item : mItems.keySet()) {
            copy.add(item);
        }

        for (final A item : copy) {
            item.someMethod();
        }
    }

    public void addItem(final A item) {
        mItems.put(item, new B());
    }

    public void removeItem(final A item) {
        mItems.remove(item);
    }
}
我不完全清楚我们为什么要以这种方式创建
副本。抛出CME是因为在for each循环运行时调用了
addItem(A)
removietem(A)

问题

  • 我对CME为何被抛出的理解正确吗

  • 如果我将for each循环替换为:

    final List<A> copy = new LinkedList<A>(mItems.keySet());
    
    final List copy=newlinkedlist(mItems.keySet())

  • 此更改是否等同于我们将要替换的每个循环的更改?据我所知,这两个代码段都在
    copy
    中创建了
    mItems.keySet()
    的浅拷贝

  • 我对CME为何被抛出的理解正确吗

    当然。这正是正在发生的事情

    如果我将for each循环替换为:

    final List<A> copy = new LinkedList<A>(mItems.keySet());
    

    解决此问题的最终列表,无需在代码中使用
    synchronized

    谢谢您的帮助。我理解为什么需要将for-each循环放在同步块中。但是,使
    addItem
    removietem
    同步的原因是什么?@user3264740您需要读写双方
    同步
    。否则,
    foreach
    循环将自由获取锁,即使
    addItem
    removietem
    可能正在进行。