Java ConcurrentHashMap中的Treemap是线程安全的吗?
我有一个嵌套贴图的例子,如下所示:Java ConcurrentHashMap中的Treemap是线程安全的吗?,java,concurrency,thread-safety,treemap,concurrenthashmap,Java,Concurrency,Thread Safety,Treemap,Concurrenthashmap,我有一个嵌套贴图的例子,如下所示: private final static Map<String, TreeMap<Long,String>> outerConcurrentMap = new ConcurrentHashMap<>(); private final static Map outerConcurrentMap=new ConcurrentHashMap(); 我知道ConcurrentHashMap是线程安全的,但是我想知道这个CHM中的
private final static Map<String, TreeMap<Long,String>> outerConcurrentMap = new ConcurrentHashMap<>();
private final static Map outerConcurrentMap=new ConcurrentHashMap();
我知道ConcurrentHashMap
是线程安全的,但是我想知道这个CHM中的TreeMap
s,它们在CHM中也是线程安全的吗
我正在进行的操作包括:
get(K)
从CHM检索树映射tailMap(K,布尔值)
方法从树映射中检索数据clear()
CHM这将如何运作;创建任何类型的对象,并将其添加到这样的映射中,对象本身就成为线程安全的?当你从地图上移除那个物体时,“线程不安全”就恢复了 假设您在多个线程中执行所有这些操作,不,这不是线程安全的 忽略您已经通过
ConcurrentHashMap
访问了TreeMap
这一事实-您最终会遇到多个线程同时访问TreeMap
,包括一个或多个线程写入映射。这是不安全的,因为对于这种情况,TreeMap
不是线程安全的:
请注意,此实现是不同步的。如果多个线程同时访问一个映射,并且至少有一个线程在结构上修改了映射,那么它必须在外部同步
假设您在多个线程中执行所有这些操作,不,这不是线程安全的 忽略您已经通过
ConcurrentHashMap
访问了TreeMap
这一事实-您最终会遇到多个线程同时访问TreeMap
,包括一个或多个线程写入映射。这是不安全的,因为对于这种情况,TreeMap
不是线程安全的:
请注意,此实现是不同步的。如果多个线程同时访问一个映射,并且至少有一个线程在结构上修改了映射,那么它必须在外部同步
一旦完成
TreeMap tm=chm.get(key)代码>您不再处于线程安全区域。特别是,如果另一个线程(通过CHM或不通过CHM)更新树映射,您可能会看到也可能看不到更改。更糟糕的是,您在tm
中的地图副本可能已损坏
一种选择是使用线程安全映射,例如ConcurrentSkipListMap。一旦您完成TreeMap tm=chm.get(key)代码>您不再处于线程安全区域。特别是,如果另一个线程(通过CHM或不通过CHM)更新树映射,您可能会看到也可能看不到更改。更糟糕的是,您在tm
中的地图副本可能已损坏
一种选择是使用线程安全映射,例如ConcurrentSkipListMap。有些场景是线程安全的,有些则不是:
1。是的,这是线程安全的,尽管在您将新创建的树映射放到CHM之前,其他线程无法看到它。但是这应该小心地实现以避免竞争条件-您应该确保检查和插入是以原子方式执行的:
// create an empty treemap somewhere before
TreeMap<Long, String> emptyMap = new TreeMap<>();
...
// On access, use putIfAbsent method to make sure that if 2 threads
// try to get same key without associated value sumultaneously,
// the same empty map is returned
if (outerConcurrentMap.putIfAbsent(key, emptyMap) == null) {
emptyMap = new TreeMap<>();
};
map = outerConcurrentMap.get(key);
//在之前的某个位置创建一个空树映射
TreeMap emptyMap=新的TreeMap();
...
//在访问时,使用putIfAbsent方法确保
//尝试同时获取没有关联值的相同密钥,
//返回相同的空映射
if(outerConcurrentMap.putIfAbsent(key,emptyMap)==null){
emptyMap=新树映射();
};
map=outerConcurrentMap.get(键);
2,3,4。否,首先需要通过显式锁定或使用synchronized
锁定此树映射<代码>树映射本身不同步
5。是的,这是在CHM上执行的操作,因此它是线程安全的
如果需要完全线程安全的排序映射,请改用ConcurrentSkipListMap
。它比TreeMap慢,但其内部结构不需要在访问期间锁定完整集合,从而使其在并发环境中有效。有些场景是线程安全的,有些则不是:
1。是的,这是线程安全的,尽管在您将新创建的树映射放到CHM之前,其他线程无法看到它。但是这应该小心地实现以避免竞争条件-您应该确保检查和插入是以原子方式执行的:
// create an empty treemap somewhere before
TreeMap<Long, String> emptyMap = new TreeMap<>();
...
// On access, use putIfAbsent method to make sure that if 2 threads
// try to get same key without associated value sumultaneously,
// the same empty map is returned
if (outerConcurrentMap.putIfAbsent(key, emptyMap) == null) {
emptyMap = new TreeMap<>();
};
map = outerConcurrentMap.get(key);
//在之前的某个位置创建一个空树映射
TreeMap emptyMap=新的TreeMap();
...
//在访问时,使用putIfAbsent方法确保
//尝试同时获取没有关联值的相同密钥,
//返回相同的空映射
if(outerConcurrentMap.putIfAbsent(key,emptyMap)==null){
emptyMap=新树映射();
};
map=outerConcurrentMap.get(键);
2,3,4。否,首先需要通过显式锁定或使用synchronized
锁定此树映射<代码>树形图