Kotlin中List分配触发ConcurrentModificationException问题解决
问题分析与解决方案
异常原因
ConcurrentModificationException 本质是多线程并发访问并修改同一集合导致的:当你调用 folderUpdatedList.ExpirationDatesArt?.toMutableList() 时,内部会遍历原集合生成副本;如果此时其他线程正在修改或遍历这个原集合,就会触发并发修改异常——哪怕你当前线程只是读取,没有主动删除元素。
可行解决方案
方案1:添加同步锁,确保线程安全访问
通过synchronized块锁定folderUpdatedList,保证同一时间只有一个线程能访问或修改其内部的ExpirationDatesArt列表,从根源避免并发冲突:
private fun joinListToUpdatedList(listToJoin: List<ExpirationDatesArt>?) { // 锁定目标对象,确保所有对ExpirationDatesArt的操作串行执行 synchronized(folderUpdatedList) { val folderUpdatedListValue = folderUpdatedList.ExpirationDatesArt?.toMutableList() if (listToJoin != null) { if (folderUpdatedListValue != null) { folderUpdatedListValue.addAll(listToJoin) val joinedUpdatedList = folderUpdatedListValue.distinctBy { it.cdean } folderUpdatedList.ExpirationDatesArt = joinedUpdatedList } else { folderUpdatedList.ExpirationDatesArt = listToJoin } } } }
注意:所有其他访问或修改folderUpdatedList.ExpirationDatesArt的代码,也需要包裹在同一个对象的synchronized块中,否则锁的作用会失效。
方案2:改用线程安全集合
将folderUpdatedList.ExpirationDatesArt的类型替换为CopyOnWriteArrayList(线程安全的列表实现),它会在每次修改时复制底层数组,遍历操作始终基于快照,不会触发并发修改异常:
// 先确保folderUpdatedList.ExpirationDatesArt的类型声明为CopyOnWriteArrayList<ExpirationDatesArt>? private fun joinListToUpdatedList(listToJoin: List<ExpirationDatesArt>?) { if (listToJoin == null) return val folderUpdatedListValue = folderUpdatedList.ExpirationDatesArt?.let { ArrayList(it) } if (folderUpdatedListValue != null) { folderUpdatedListValue.addAll(listToJoin) val joinedUpdatedList = folderUpdatedListValue.distinctBy { it.cdean } folderUpdatedList.ExpirationDatesArt = CopyOnWriteArrayList(joinedUpdatedList) } else { folderUpdatedList.ExpirationDatesArt = CopyOnWriteArrayList(listToJoin) } }
这种方式不需要手动加锁,但因为每次修改都会复制数组,适合读多写少的场景。
内容的提问来源于stack exchange,提问作者Quentin
相关产品推荐
相关产品推荐

