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) } }
这样做的优势:
- 同步块仅负责复制操作,锁持有时间极短,减少并发冲突概率
- 遍历的是独立副本,原map即使因为GC触发自动清理,也不会干扰遍历过程,彻底避免并发修改异常
内容的提问来源于stack exchange,提问作者growse
相关产品推荐
相关产品推荐

