首页 > 解决方案 > 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) {;}
        }
    }
}

标签: javamultithreadingconcurrencyhashmap

解决方案


编辑:在您的示例中,地图不会在其他线程中被访问,只有地图引用的对象。

由于使用它们的方式,对象本身应该是线程安全的。

注意:如果您使用 parallelStream() 代码会更简单。


其他线程会看到对 hashmap 成员的更改吗?

可能,但没有保证

如果没有,是否会在声明工作中添加 volatile,

volatileon the field 仅在对 Map 的引用上添加了一个读取障碍。(除非您将字段更改为指向另一个 Map ,否则您将遇到写入障碍。)

还是只保证其他线程看到结构的变化?

不,只保证看到对myMap参考的更改,而不是对地图或地图中的任何内容的更改。即保证很浅。

有多种方法可以提供线程安全,但最简单的方法是对synchronized对象进行读写操作。您可以对volatile字段进行一些技巧,但是这在很大程度上取决于您正在做什么,这是否会起作用。


推荐阅读