【问题标题】:Can I get iterators from an ArrayList in multiple threads and use all of them safelly?我可以从多个线程中的 ArrayList 获取迭代器并安全地使用它们吗?
【发布时间】:2014-06-10 15:36:44
【问题描述】:

我有一个由多个线程共享的 ArrayList 实例。它在一个同步块中被初始化(因此有一个内存屏障使其对所有线程可见)并且所有线程只能从中读取。 ArrayList 永远不会改变。

我已经在网上阅读了很多帖子,但无论我如何阅读,我仍然不清楚阅读是否安全。如果我在每个线程中从它那里获得一个迭代器,那么迭代器是否会共享一些在迭代时会改变的状态等。我不共享迭代器,每个线程都有它自己的。

无论我如何进行读取,读取是否都是线程安全的?

【问题讨论】:

  • 只读总是线程安全的。共享迭代器可能不是线程安全的,因为每个迭代器都有状态,并且从迭代器中读取会改变该状态,但如果每个线程都有自己的迭代器,那可能没问题。
  • @user3580294: ...it's probably OK... 是我问这个的原因。是肯定的还是可能好的? :)
  • 哦,好吧,绝对没问题。只要您不共享更改状态并且不更改共享状态,就可以了。所以不要使用Iterator#remove()
  • 如果每个线程都有自己的迭代器,那没关系。但是,您不能在线程之间共享单个迭代器

标签: java multithreading collections thread-safety


【解决方案1】:

只要每个线程都有自己的迭代器,就可以了。

您需要担心同步的唯一情况是当一个线程正在修改(写入)共享数据结构而其他线程正在读取它时。这可能导致数据结构处于不一致的状态(想象一下,当调度程序pre-empts it/切换到另一个线程时,线程还没有完成修改)。

当所有线程都只读取时,数据永远不会处于不一致的状态,你也不用担心线程同步问题。

【讨论】:

  • 这适用于任何收藏之王吗?以任何你喜欢的方式阅读它总是安全的?
  • 是的,这适用于任何集合/数据结构。
【解决方案2】:

只要迭代器用于只读,这将按预期工作。此外,迭代器是快速失败的,因为它可能会由于以下原因引发 ConcurrentModificationException:

  1. 在多线程处理中,如果一个线程试图修改一个 在另一个线程对其进行迭代时收集。
  2. 在单线程或多线程中,如果在创建 迭代器,使用自己的方法修改集合而不是 使用迭代器自己的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    相关资源
    最近更新 更多