ConcurrentHashMap更新存在值线程安全

时间:2016-03-29 07:13:38

标签: java multithreading java.util.concurrent

我想使用包含一些结果的并发哈希映射

ConcurrentHashMap<Long,AtomicInteger>

如果key不存在则添加新条目,或者按键和增量获取值,如下所示:

if(map.contains(key))
  map.get(key).addAndGet(1);
else
  map.put(key,new AtomicInteger(1));    
放置操作不安全,如何解决这个问题? put操作应该在synchronized块内吗?

3 个答案:

答案 0 :(得分:3)

put()操作本身是以线程安全的方式实现的,即如果你输入相同的密钥,它将在内部同步。

但是,呼叫不是,即两个线程可以同时添加新密钥。你可以尝试putIfAbsent(),如果你得到一个返回值(即不为null),你可以调用get方法。因此,您可以像这样更改代码:

//this only adds a new key-value pair if there's not already one for the key
if( map.putIfAbsent(key,new AtomicInteger(1)) != null ) {    
  map.get(key).addAndGet(1);
}

或者,如果您正在使用Java 8,则可以使用compute()方法,该方法根据JavaDoc原子执行。您传递的函数将检查该值是否已存在。由于整个呼叫是同步的,你可能甚至不需要使用AtomicInteger(取决于你对该值做了什么)。

答案 1 :(得分:0)

您应该使用ConcurrentHashMap.putIfAbsent(K key, V value)并注意返回值。

答案 2 :(得分:0)

在Java 8中,您可以使用ConcurrentHashMap的computeIfAbsent提供初始值:

>>> ' '.join(map(lambda c: chr(ord('A') + int((ord(c) - ord(' ')) % 7)) + str(int((ord(c) - ord(' ')) / 7)), input()))
3.14159ABC265
'F2 A2 D2 G2 D2 A3 E3 F4 G4 A5 E2 B3 A3'
>>>