Java ConcurrentHashMap更新存在线程安全值
我想使用包含一些结果的并发哈希映射Java ConcurrentHashMap更新存在线程安全值,java,multithreading,java.util.concurrent,Java,Multithreading,Java.util.concurrent,我想使用包含一些结果的并发哈希映射 ConcurrentHashMap<Long,AtomicInteger> put操作不安全,如何解决这个问题?put操作是否应该在同步块中?您应该使用ConcurrentHashMap.putIfAbsent(K键,V值)并注意返回值。put()操作本身是以线程安全的方式实现的,即如果您放置相同的键,它将在内部同步 但是,调用不是,即两个线程可以同时添加一个新密钥。您可以尝试putIfAbsent(),如果您得到一个返回值(即非null),您可
ConcurrentHashMap<Long,AtomicInteger>
put操作不安全,如何解决这个问题?put操作是否应该在同步块中?您应该使用
ConcurrentHashMap.putIfAbsent(K键,V值)
并注意返回值。put()操作本身是以线程安全的方式实现的,即如果您放置相同的键,它将在内部同步
但是,调用不是,即两个线程可以同时添加一个新密钥。您可以尝试putIfAbsent()
,如果您得到一个返回值(即非null),您可以调用get方法。因此,您可以这样更改代码:
if(map.contains(key))
map.get(key).addAndGet(1);
else
map.put(key,new AtomicInteger(1));
//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);
}
或者,如果您使用的是Java8,则可以使用
compute()
方法,根据JavaDoc,该方法是原子执行的。然后,您传递的函数将检查该值是否已经存在。由于整个调用是同步的,您甚至可能不需要使用AtomicInteger
(取决于您对该值执行的其他操作)。在Java 8中,您可以使用ConcurrentHashMap提供初始值:
map.computeIfAbsent(key, new AtomicInteger(0)).addAndGet(1)
这不仅仅是put操作——显示的整个条件块必须在同步块中。或者,您可以使用
putIfAbsent
。使用putIfAbsent似乎更简单。我在同步块中使用了双重检查,而不是在整个条件块中使用。