【问题标题】:ConcurrentModificationException in iterator.next()iterator.next() 中的 ConcurrentModificationException
【发布时间】:2015-05-05 20:22:40
【问题描述】:

我在后台线程中有下一个代码

private List<IStartAction> mActions = Collections.synchronizedList(new ArrayList<IStartAction>()); 

protected void removeNonApplicableActions() {
        Iterator<IStartAction> iterator = mActions.iterator();
        while (iterator.hasNext()) {
            IStartAction action = iterator.next();
            if (!action.isApplicable()) {
                iterator.remove();
            }
        }
    }

当我在主线程中运行它时,会将 ConcurrentModificationException 放入 iterator.next()。 为什么会这样?我使用线程安全的集合并通过迭代器删除项目。仅在此线程中使用的集合。

【问题讨论】:

  • 同步表示在特定条件下可以在1个以上的线程中修改列表(请参阅javadoc的synchronizedList()方法)。这是一个不同的问题,您同时迭代和删除。请使用 listIterator 而不是普通的迭代器。使用 listIterator() 方法。
  • 您能否提供一个代码的最小工作示例,以便我们重现该问题?
  • ConcurrentModificationException 并不是必然表示您有多个线程在修改您的列表,而是您同时在遍历您的列表并同时对其进行修改。跨度>
  • 这看起来很奇怪/有问题。请 MCVE。
  • isApplicable() 是做什么的?它是否以任何方式修改mActions

标签: java multithreading java.util.concurrent


【解决方案1】:

同步集合的线程安全仅适用于一个方法调用。在方法调用之间,锁被释放,另一个线程可以锁定集合。如果您执行两个操作,则任何事情都可能在此期间发生,除非您自己锁定它。例如

// to add two elements in a row, you must hold the lock.
synchronized(mAction) {
    mAction.add(x);
    // without holding the lock, anything could happen in between
    mAction.add(y);
}

与迭代同步集合类似,您必须持有锁,否则在对迭代器的方法调用之间可能会发生任何事情。

synchronized (mAction) {
    for(Iterator<IStartAction> iter = mActions.iterator(); iter.hashNext();) {
        IStartAction action = iter.next();
        if (!action.isApplicable()) {
            iter.remove();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2017-02-10
    • 2015-09-15
    • 2011-08-29
    • 1970-01-01
    • 2021-03-02
    • 2023-03-21
    相关资源
    最近更新 更多