You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中同步WeakHashMap执行forEach为何抛出ConcurrentModificationException?

WeakHashMap遍历触发ConcurrentModificationException的原因与解决方法

你遇到的问题根源在于WeakHashMap的自动清理机制,和外部线程主动修改无关,具体原因如下:

  • WeakHashMap的key是弱引用类型,当这些key没有被其他强引用持有时,会被GC回收。WeakHashMap会在迭代、get等操作时,自动移除这些已被GC回收的key对应的条目——这个清理操作属于修改map的结构。
  • 你用synchronized(listeners)只能阻止其他线程修改map,但拦不住WeakHashMap自身在迭代过程中触发的自动清理。一旦迭代时发生了这种内部清理,迭代器就会检测到map结构变化,抛出ConcurrentModificationException。

解决方法很直接:遍历前先把当前有效的listener复制到一个独立的列表,再遍历这个副本,避开原map的结构变化影响:

fun notifyChanged(property: KProperty<*>) {
    val properties = listOf(property.name)
    // 同步块内复制所有当前有效的listener到列表
    val activeListeners = synchronized(listeners) {
        ArrayList(listeners.keys)
    }
    // 遍历副本,不受原map后续变化影响
    activeListeners.forEach { it.onPreferenceChanged(properties) }
}

这样做的优势:

  1. 同步块仅负责复制操作,锁持有时间极短,减少并发冲突概率
  2. 遍历的是独立副本,原map即使因为GC触发自动清理,也不会干扰遍历过程,彻底避免并发修改异常

内容的提问来源于stack exchange,提问作者growse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:20:28