在处理线上崩溃时,发现一处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();
}
}