简体   繁体   中英

ConcurrentHashMap update exists value thread safe

I want to use the concurrent hash map holding some results,

ConcurrentHashMap<Long,AtomicInteger>

add a new entry if key not exists,or get value by key and increment,like this:

if(map.contains(key))
  map.get(key).addAndGet(1);
else
  map.put(key,new AtomicInteger(1));    

the put operation is not thead safe,how to solve this problem? Is put operation should within synchronized block?

The put() operation itself is implemented in a threadsafe way, ie if you put the same key it will be synchronized internally.

The call, however, isn't, ie two threads could add a new key simultaneously. You could try putIfAbsent() and if you get a return value (ie not null) you could call the get method. Thus you could change your code like this:

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

Alternatively if you're using Java 8 you could use the compute() method which according to the JavaDoc is performed atomically. The function you pass would then check whether the value already exists or not. Since the whole call is synchronized you probably wouldn't even need to use a AtomicInteger (depends on what else you are doing with the value).

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

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

map.computeIfAbsent(key, new AtomicInteger(0)).addAndGet(1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM