有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java类之间并发性不一致的HashMap

我有一个类,它有一个HashMap作为公共字段:

public static final HashMap<String, String> map = new HashMap<String, String>();

在类B(它是多线程的,实现可运行的)中,我做了一些PUT

现在,在C班,我试着从地图上读。但是地图的变化并没有反映在C类中

我没有在任何地方存储任何引用,但我通过类名访问映射

A.map.put("hi", "hello");     //in thread B
A.map.get("hi");              //in thread C

我确信我在调用put()之后调用get()

我认为并发性可能有问题,于是我将HashMap更改为Hashtable,但它仍然是一样的

我用尽可能少的代码复制了这个问题

public class A {
    public static final HashMap<String, String> map = new HashMap<String, String>();

    public static void main(String[] args){
        while(true);
    }
}

public class B {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(true){
            String s = sc.nextLine();
            A.map.put(s, "true");
            System.out.println(A.map.size());
        }
    }
}

public class C {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(true){
            sc.nextLine();
            System.out.println(A.map.size());
        }
    }
}

我可以看到B类印刷品的尺寸在增加,但C类印刷品的尺寸始终为零

我是不是遗漏了什么


共 (1) 个答案

  1. # 1 楼答案

    当从不同线程执行操作时,您希望在相同的对象上强制执行同步

    目前,您没有进行任何同步,因此无法工作

    因此,您有两种选择:

    1. Collections.synchronizedMap(new HashMap<>());将其包装到一个同步映射中。这将对所有操作强制同步,即使它们来自同一线程

    2. 在地图上执行操作时使用相同的锁定。我不会建议使用后一种方法,除非您将在一个线程上连续执行大量操作,而另一个线程不需要知道这些操作

    根据@Ziker的建议,第三种选择是使用ConcurrentHashMap,它提供了与在Collections.synchronizedMap中包装它相同的线程安全性,但成本并不相同,这意味着这应该是您的首选选择