在Java中防止零星的ConcurrentModificationException的最佳做法是什么?

时间:2011-01-11 07:51:54

标签: java thread-safety concurrentmodification

用于迭代列表或映射的代码序列会阻止ConcurrentModificationException?我们的代码中有反复和零星的ConcurrentModificationException。这个问题有两个原因。

  1. 另一个线程在迭代时更改列表
  2. 循环中调用的方法正在更改列表。
  3. 问题1可以通过循环同步来解决。但是,如果在循环中调用外来代码(例如原因2),则这很糟糕。

    问题2可以通过列表或地图的副本来解决。

    这意味着列表或映射必须在循环之前复制到同步块中。有更好的解决方案吗?

    一些示例代码:

    public void todoSomeThings( Map<Abc, Object> map ){
        for( Abc abc : map.keySet() ){
            abc.todoSomeThings();
        }
    }
    

2 个答案:

答案 0 :(得分:7)

您是否考虑过使用java.util.concurrent中的并发集合?很难提供比这更好的建议,说实话......我们需要更多细节。

需要注意的一点是,如果您在线程之间共享可变集合,并且可变集合暴露于您的大量代码中,而您在迭代时不知道可能会改变什么,那么您< em>可能想要考虑更改您的设计。不可变的集合通常可以保持清洁,有时(但不总是)以某些性能为代价。开始使用它们可能更难,但您可能会发现之后更容易推理您的代码。

答案 1 :(得分:3)

一个公平的警告:使用j.u.c(java.util.concurrent)将删除错误但你将遇到更糟糕的情况,即种族更新,陈旧读取等。最佳做法是

了解您的数据结构,使用状态......或者至少(不是最好的)使用锁。