首页 > 解决方案 > 线程安全的 ArrayList 合并:这行得通吗?

问题描述

  private static final ExecutorService ES = Executors.newWorkStealingPool();

  public Future<List<String>> isThisSafe() {
    List<String> a = new ArrayList<>();
    a.add("a");
    List<String> b = new ArrayList<>();
    b.add("b");

    return ES.submit(() -> {
      a.addAll(b);
      return a;
    });
  }

我会说线程 X 是调用 isThisSafe() 的线程。线程 Y 运行提交给 ExecutorService 的 Callable。

现在,我认为这行得通。

✓ 这两个 ArrayList 发布到 Y 后,再也不会被 X 修改

✓ ArrayList 'a' 被线程 Y 修改,但 X 不持有对 'a' 的引用。返回的对 'a' 的引用将被视为“新的”,因此 X 将从 MM 中提取此引用。

但是我的第二点有问题吗?也许我误解了内存模型。

标签: javamultithreadingconcurrencythread-safety

解决方案


线程 X 安全地将对象发布a给线程 Y,并且在 Y 成功之前不做任何修改。所以对象a从线程 X 安全地发布到线程 Y。

此外,线程中的所有操作都发生在任何其他线程从该线程Future.get()上成功返回之前。从线程 X 返回后,Future.get()可以看到线程 Y 对对象所做的所有更改a

所以根据我们的线程安全分析,我们可以断定这段代码是线程安全的。


推荐阅读