存储在 ConcurrentHashMap 中的原子递增计数器

我想从 Web 应用中的不同位置收集一些指标。为了简单起见,所有这些都将是计数器,因此唯一的修饰符操作是将它们递增1。

增量将是并发的,并且经常发生。读取(转储统计信息)是一种罕见的操作。

我正在考虑使用 ConcurrentHashMap。问题是如何正确递增计数器。由于地图没有“增量”操作,我需要先读取当前值,递增它,而不是将新值放入地图中。如果没有更多代码,这不是原子操作。

有没有可能在没有同步的情况下实现这一点(这将破坏 ConcurrentHashMap 的目的)?我需要看看番石榴吗?

感谢您的指点。


附言:
SO(在Java中增加Map值的最有效方法)有一个相关的问题,但重点是性能而不是多线程

更新
对于那些通过搜索同一主题到达这里的人来说:除了下面的答案之外,还有一个有用的演示文稿,偶然涵盖了相同的主题。请参阅幻灯片 24-33。


答案 1

在Java 8中:

ConcurrentHashMap<String, LongAdder> map = new ConcurrentHashMap<>();

map.computeIfAbsent("key", k -> new LongAdder()).increment();

答案 2

Guava的新AtomicLongMap(第11版)可能会满足这一需求。


推荐