防止 Java 中偶发的 ConcurrentModificationException 的最佳实践是什么?

发布于 2024-10-11 08:47:10 字数 478 浏览 10 评论 0原文

哪个用于迭代列表或映射的代码序列可以防止 ConcurrentModificationException?我们的代码中反复出现零星的 ConcurrentModificationException。造成这个问题的原因有两个。

  1. 另一个线程在迭代时更改列表
  2. 循环中调用的方法正在更改列表。

问题1可以通过循环同步来解决。但如果像原因 2 那样在循环中调用外来代码,这就很糟糕了。

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

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

一些示例代码:

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

Which code sequence for iterating over a list or map prevent ConcurrentModificationException? We have repeatedly and sporadic ConcurrentModificationException in our code. There are 2 causes for the problem.

  1. Another thread change the list on iterating
  2. A method which is called in the loop is changing the list.

Problem 1 can be solved with a synchronized around the loop. But this is bad if alien code is called in the loop like cause 2.

Problem 2 can be solved with a copy of the list or map.

This means the list or map must be copy in a synchronized block before the loop. Are there a better solution?

Some sample code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒中人 2024-10-18 08:47:11

您是否考虑过使用 < 中的并发集合代码>java.util.concurrent?老实说,很难给出比这更好的建议……我们需要更多细节。

需要注意的一点是,如果您在线程之间共享可变集合,并且可变集合暴露于大量代码,以至于您不知道在迭代时可能会发生什么变化,那么您可能会如果可能的话,想考虑改变你的设计。不可变集合通常可以使事物保持干净,有时(但并非总是)会牺牲一些性能。一开始使用它们可能会比较困难,但之后您可能会发现更容易推理您的代码。

Have you considered using the concurrent collections in java.util.concurrent? It's hard to give much better advice than that, to be honest... we'd need more details.

One point to note is that if you've got mutable collections shared between threads, and mutable collections exposed to so much of your code that you don't know what might be mutating it while you're iterating, then you might want to consider changing your design if possible. Immutable collections can often keep things cleaner, sometimes (but not always) at the cost of some performance. They can be harder to work with to start with, but you're likely to find it easier to reason about your code afterwards.

寂寞笑我太脆弱 2024-10-18 08:47:11

一个公平的警告:使用 juc (java.util.concurrent) 将消除错误,但您可能会遇到更糟糕的情况,即竞赛更新、陈旧读取等。最佳实践是

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

A fair warning: using j.u.c (java.util.concurrent) will remove the errors but you will be running into possibly worse case, i.e. race updates, stale reads, etc. The best practice is

Know your data structures, use states... or at least (which is not best) use locks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文