在处理线上崩溃时,发现一处list出现了多线程操作导致的崩溃:

for(Listener listener : listenerList) {//崩溃处
    listener.update();
}

但排查中,发现这一list已经是使用了Collections.synchronizedList:

list = Collections.synchronizedList(new ArrayList<>());

后续继续排查发现这是因为Collections.synchronizedList的原因。

Collections.synchronizedList特点是:对读写删加锁,遍历不加锁(根据实际业务需要,自行加锁),源码如下:

由于foreach也是基于迭代器实现的,即Collections.synchronizedList类型的list在执行foreach是没加锁的,多线程操作下是会出现 ConcurrentModificationException崩溃。

解决方式也简单,对遍历list的代码块加锁即可:

synchronized(listenerList) {
    for(Listener listener : listenerList) {//崩溃处
        listener.update();
    }
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐