我有一个Map
ConcurrentHashMap
,这是我想知道的问题。
我在Map
内有另一个ConcurrentHashMap
,这是一个普通的Map
。
这种情况对于并发性是否合适,或者我是否必须使用ConcurrentHashMap
作为
private Map<String, Map<Integer,Float>> calculations = null;
private Constructor(){
calculations = new ConcurrentHashMap<>();
}
private void foo(){
calculations.add("XXX",new HashMap<>()); // this one ?
calculations.add("XXX",new ConcurrentHashMap<>()); // or this one ?
}
哪种工具适用于并发?
答案 0 :(得分:1)
我相信你应该使用ConcurrentHashMap
,如果你的目标是从多个线程进行多线程和并发修改而你不能拥有空值,因为ConcurrentHashMap
不能拥有它们。否则,您应该使用普通的HashMap。
╔═══════════════╦═══════════════════╦═══════════════════╗
║ Property ║ HashMap ║ ConcurrentHashMap ║
╠═══════════════╬═══════════════════╬═══════════════════╣
║ Null ║ allowed ║ not allowed ║
║ values/keys ║ ║ ║
╠═══════════════╬═══════════════════╬═══════════════════║
║Is thread-safe ║ no ║ yes ║
╠═══════════════╬═══════════════════╬═══════════════════║
║ Lock ║ not ║ locks the portion ║
║ mechanism ║ applicable ║ ║
╠═══════════════╬═══════════════════╩═══════════════════╣
║ Iterator ║ fail-fast ║ fail-safe ║
╚═══════════════╩═══════════════════════════════════════╝
答案 1 :(得分:1)
我建议将ConcurrentHashMaps用于value-Maps - 性能损失可以忽略不计 - 因为您无法保证不会同时访问这些映射。
如果只有容器映射是线程安全的,那么您只能对该容器进行线程安全访问,但您对这些值没有线程安全性。换句话说,你不能阻止,两个线程获得对相同值映射的引用并同时访问它(至少有一个线程执行写操作)。
例如:
T1 T2 HashMap T3 ContainerMap
| | +<-create-+ |
| | | +-put(map)->+ //thread safe
+------get(map)------------------>+ //thread safe
I<--------------------------------/
| +-------get(map)------------->+ //thread safe
| I<----------------------------/
| | |
+-put(v)->--+
| +put(v)>+ //concurrent access, not thread safe
如果值映射是不可变的(Collections.unmodifiableMap()
),你可以没问题,否则你的线程会陷入无限循环的风险。
另一种方法是同步值映射(synchronized(valueMap)
)上的访问,或使用另一种锁定机制(即StampedLock用于乐观读锁定)。
答案 2 :(得分:0)
根据您提供的信息,无法回答您的问题。
您在Map
内存储对Map
个对象的引用这一事实并不意味着什么。重要的是您的程序如何使用任何特定的地图。如果多个线程访问任何特定的映射对象,并且IF至少有一个线程更新该映射,并且对该映射的IF访问不受任何更高级别锁定的保护;那么 地图应该是一个线程安全的实现,例如ConcurrentHashMap
。