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 楼答案
当从不同线程执行操作时,您希望在相同的对象上强制执行同步
目前,您没有进行任何同步,因此无法工作
因此,您有两种选择:
用
Collections.synchronizedMap(new HashMap<>());
将其包装到一个同步映射中。这将对所有操作强制同步,即使它们来自同一线程在地图上执行操作时使用相同的锁定。我不会建议使用后一种方法,除非您将在一个线程上连续执行大量操作,而另一个线程不需要知道这些操作
根据@Ziker的建议,第三种选择是使用
ConcurrentHashMap
,它提供了与在Collections.synchronizedMap
中包装它相同的线程安全性,但成本并不相同,这意味着这应该是您的首选选择