ConcurrentHashMap更新存在值线程安全
ConcurrentHashMap update exists value thread safe
我想使用保存一些结果的并发哈希映射,
ConcurrentHashMap<Long,AtomicInteger>
如果键不存在则添加一个新条目,或者通过键和增量获取值,就像这样:
if(map.contains(key))
map.get(key).addAndGet(1);
else
map.put(key,new AtomicInteger(1));
put操作不安全,如何解决这个问题? put 操作应该在 synchronized 块内吗?
您应该使用 ConcurrentHashMap.putIfAbsent(K key, V value)
并注意 return 值。
put()
操作本身是以线程安全的方式实现的,即如果您输入相同的密钥,它将在内部同步。
然而,调用不是,即两个线程可以同时添加一个新密钥。您可以尝试 putIfAbsent()
,如果您得到 return 值(即不为空),您可以调用 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
(取决于您对值进行的其他操作)。
在 Java 8 中,您可以使用 ConcurrentHashMap 的 computeIfAbsent 来提供初始值:
map.computeIfAbsent(key, new AtomicInteger(0)).addAndGet(1)
我想使用保存一些结果的并发哈希映射,
ConcurrentHashMap<Long,AtomicInteger>
如果键不存在则添加一个新条目,或者通过键和增量获取值,就像这样:
if(map.contains(key))
map.get(key).addAndGet(1);
else
map.put(key,new AtomicInteger(1));
put操作不安全,如何解决这个问题? put 操作应该在 synchronized 块内吗?
您应该使用 ConcurrentHashMap.putIfAbsent(K key, V value)
并注意 return 值。
put()
操作本身是以线程安全的方式实现的,即如果您输入相同的密钥,它将在内部同步。
然而,调用不是,即两个线程可以同时添加一个新密钥。您可以尝试 putIfAbsent()
,如果您得到 return 值(即不为空),您可以调用 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
(取决于您对值进行的其他操作)。
在 Java 8 中,您可以使用 ConcurrentHashMap 的 computeIfAbsent 来提供初始值:
map.computeIfAbsent(key, new AtomicInteger(0)).addAndGet(1)