java - 线程安全的 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 中提取此引用。
但是我的第二点有问题吗?也许我误解了内存模型。
解决方案
线程 X 安全地将对象发布a
给线程 Y,并且在 Y 成功之前不做任何修改。所以对象a
从线程 X 安全地发布到线程 Y。
此外,线程中的所有操作都发生在任何其他线程从该线程Future.get()
上成功返回之前。从线程 X 返回后,Future.get()
可以看到线程 Y 对对象所做的所有更改a
。
所以根据我们的线程安全分析,我们可以断定这段代码是线程安全的。
推荐阅读
- list - 过滤变量 map+list
- java - 为每个报告插件调用 Maven“进程类”阶段(多次执行)
- c# - 从 Adomd 执行时,mdx 查询“操作已取消”
- apache-spark - 大数据框自连接
- python - 使用步幅为 1 的最大池时的维度问题
- c# - 如何在C#中将带有图像的行转换为Base64中的excel文件读取
- visual-studio-code - 如何删除 Visual Code 中的背面标签?
- javascript - Repopulating table data in Laravel Pagination using JQUERY and AJAX
- c# - 2021 年适用于 C# 的 Facebook Graph API 客户端 - 它存在吗?
- salesforce - 按参考字段 SQQL Salesforce 分组