java - HashMap成员的并发修改
问题描述
我定义了一张地图
private static HashMap<Object, Object> myMap;
它填充在单个线程中,然后该单个线程产生更多线程来更改地图元素内的数据,但不更改地图结构(没有删除/放置/等)。此外,每个线程只更改一个映射的唯一成员(没有两个线程更改同一个成员)。
我的问题是:一旦所有更改完成,主线程会看到哈希图成员的更改吗?如果没有,是否将 volatile 添加到声明中,或者它只会保证其他线程看到结构的更改?谢谢
编辑:希望以更清晰的方式突出我正在做的事情的代码
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TestingRandomStuff {
public static void main(String[] args) throws Exception {
HashMap<Object, Object> myMap = new HashMap();
ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//myMap is populated by this thread, and the objects inside are initialized, but are left largely empty
populate();
for (Object o : myMap.values()) {
Runnable r = new Task(o);
pool.execute(r);
}
pool.shutdown();
try {
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {;}
//How do I gurantee that the objects inside myMap are displayed correctly with all the data that was just loaded by seperate threads,
//or is it already guranteed?
displayObjectData();
}
public static class Task implements Runnable {
private Object o;
public Task(Object o) {this.o = o;}
public void run() {
try {
o.load(); //o contains many complicated instance variables that will be created and written to
} catch (Exception e) {;}
}
}
}
解决方案
编辑:在您的示例中,地图不会在其他线程中被访问,只有地图引用的对象。
由于使用它们的方式,对象本身应该是线程安全的。
注意:如果您使用 parallelStream() 代码会更简单。
其他线程会看到对 hashmap 成员的更改吗?
可能,但没有保证
如果没有,是否会在声明工作中添加 volatile,
volatile
on the field 仅在对 Map 的引用上添加了一个读取障碍。(除非您将字段更改为指向另一个 Map ,否则您将遇到写入障碍。)
还是只保证其他线程看到结构的变化?
不,只保证看到对myMap
参考的更改,而不是对地图或地图中的任何内容的更改。即保证很浅。
有多种方法可以提供线程安全,但最简单的方法是对synchronized
对象进行读写操作。您可以对volatile
字段进行一些技巧,但是这在很大程度上取决于您正在做什么,这是否会起作用。
推荐阅读
- javascript - 如何用玩笑测试更新组件状态的函数
- python-3.x - Pandas read_csv 方法在使用 ISO 8859-15 编码时无法正确获取“-”字符
- containers - 服务网格与 IBM IIB 或 Oracle ESB 等 2010 年 ESB 解决方案有何不同
- google-chrome - 无法在 chrome 扩展中加载 tensorflowJS 模型
- python - Miniconda 更新到新的 bash 会话
- c# - 如何在 C# 中以异步方式等待多个 WaitHandle 数组并支持取消?
- amazon-dynamodb - 使用 DynamoDB 并进行非规范化以尝试将关系数据转换为 NoSql 思维方式
- typescript - 带有斜线路径的导出模块
- amazon-web-services - 如何为 SageMaker 拉取预先构建的 docker 映像?
- logical-operators - CLIPS 中的测试函数是否有相等运算符?另外,嵌套或如何工作?