ArrayList可以在多线程环境中用于只读目的吗?

时间:2014-02-11 22:52:44

标签: java multithreading arraylist

我很少ArrayList<T>包含用户定义的对象(例如List<Student>, List<Teachers>)。这些对象本质上是不可变的,即没有提供setter - 而且,由于问题的性质,“没有人”会试图修改这些对象。填充'ArrayList'后,不允许/可能进一步添加/删除对象。所以List不会动态变化。

在这样的条件下,多线程(同时)可以安全地使用这些数据结构(即ArraList)吗?每个线程都只读取对象属性,但没有“set”操作可能。

所以,我的问题是我能依靠ArrayList吗?如果没有,在这种情况下可以使用哪些其他较便宜的数据结构?

2 个答案:

答案 0 :(得分:2)

如果在安全发布之后从未修改过线程,则可以在线程之间共享任何对象或数据结构。正如评论中所提到的,初始化ArrayList的写入与其他线程获取引用的读取之间必须存在* before-before *关系。

E.g。如果您在启动其他线程之前或在将列表中的任务提交到ArrayList之前完全设置ExecutorService,那么您就是安全的。

如果线程已在运行,则必须使用其中一个线程安全机制将ArrayList引用移交给其他线程,例如把它放在BlockingQueue上。

即使是最简单的表单,例如将引用存储到static finalvolatile字段也可以。

请记住,之后永远不要修改对象的前提条件必须始终保持不变。建议通过使用Collections.unmodifiableList(…)包装列表来强制执行该约束,并在发布之前忘记原始列表引用:

class Example {
  public static final List<String> THREAD_SAFE_LIST;
  static {
    ArrayList<String> list=new ArrayList<>();
    // do the setup
    THREAD_SAFE_LIST=Collections.unmodifiableList(list);
  }
}

class Example {
  public static final List<String> THREAD_SAFE_LIST
    =Collections.unmodifiableList(Arrays.asList("foo", "bar"));
}

答案 1 :(得分:1)

是的,您应该能够将数组传递到每个线程中。只要在任何线程可能获取信息之前完成数组的写入,就不应该存在访问错误。