是ConcurrentHashMap线程内的Treemap安全吗?

时间:2015-04-08 12:26:01

标签: java concurrency thread-safety treemap concurrenthashmap

我有一个嵌套地图的例子如下:

private final static Map<String, TreeMap<Long,String>> outerConcurrentMap = new ConcurrentHashMap<>();

我知道ConcurrentHashMap是线程安全的,但是我想了解这个CHM控件的TreeMap,它们在CHM中是否也是线程安全的?

我正在进行的操作是:

  1. 如果找不到特定密钥 - &gt;创建新的TreeMap并反对密钥。
  2. 如果找到密钥,则获取TreeMap,然后更新它。
  3. 使用get(K)从CHM检索TreeMap。
  4. 使用tailMap(K,boolean)方法从TreeMap中检索数据。
  5. clear() CHM。
  6. 在这种情况下我想要一个线程安全的结构。上面的实现是否是线程安全的?如果没有,请提出解决方案。

5 个答案:

答案 0 :(得分:4)

一旦完成TreeMap<?, ?> tm = chm.get(key);,您就不再处于线程安全领域。特别是,如果另一个线程更新树形图(通过CHM或不更新),您可能会看到或可能看不到更改。更糟糕的是,您在tm中的地图副本可能已损坏......

一种选择是使用线程安全映射,例如ConcurrentSkipListMap。

答案 1 :(得分:2)

简单回答:不。

如果您的地图是ConcurrentHashMap,那么影响您的hashmap状态的所有操作都是线程安全的。 根本不是意味着存储在该地图中的对象变得线程安全。

如何运作;你创建任何类型的对象,并通过将其添加到这样的地图,对象本身变得线程安全吗?当你从地图中删除该对象时,&#34;线程 - 不安全&#34;恢复了吗?!

答案 2 :(得分:2)

假设您在多个线程中执行所有这些操作,不,它不是线程安全的。

忽略您通过TreeMap 访问 ConcurrentHashMap的事实 - 您最终会同时访问TreeMap多个线程,包括其中一个或多个写入地图。这不安全,因为TreeMap对于这种情况不是线程安全的:

  

请注意,此实现未同步。如果多个线程同时访问映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。

答案 3 :(得分:1)

有些场景是线程安全的,有些则不是:

1。是的,这是线程安全的,但是在您将其添加到CHM之前,其他线程无法看到新创建的TreeMap。但是应该谨慎实施以避免竞争条件 - 你应该确保以原子方式执行检查和插入:

// 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);

2,3,4。不,您首先需要通过显式锁定或使用synchronized锁定此TreeMap。 TreeMap本身并不同步。

5. 是的,这是在CHM上执行的操作,因此它是线程安全的。

如果您需要完全线程安全的有序地图,请改用ConcurrentSkipListMap。它比TreeMap慢,但其内部结构不需要在访问期间锁定完整集合,从而使其在并发环境中有效。

答案 4 :(得分:0)

TreeMap本身不应该是线程安全的。由于只有ConcurrentHashMap的方法有效。

您可以做的是:

private final static Map<String, SortedMap <Long,String>> outerConcurrentMap= new ConcurrentHashMap<String, SortedMap <Long,String> >();

static {
    // Just an example
    SortedMap map = Collections.synchronizedSortedMap(new TreeMap(...));
    outerConcurrentMap.put("...",map);
}