【发布时间】:2020-10-13 22:31:52
【问题描述】:
当通过ConcurrentHashMap 中的键递增并发计数器时,使用常规Int 作为值是否安全,还是必须使用AtomicInteger?例如考虑以下两种实现
ConcurrentHashMap[String, Int]
final class ExpensiveMetrics(implicit system: ActorSystem, ec: ExecutionContext) {
import scala.collection.JavaConverters._
private val chm = new ConcurrentHashMap[String, Int]().asScala
system.scheduler.schedule(5.seconds, 60.seconds)(publishAllMetrics())
def countRequest(key: String): Unit =
chm.get(key) match {
case Some(value) => chm.update(key, value + 1)
case None => chm.update(key, 1)
}
private def resetCount(key: String) = chm.replace(key, 0)
private def publishAllMetrics(): Unit =
chm foreach { case (key, value) =>
// publishMetric(key, value.doubleValue())
resetCount(key)
}
}
ConcurrentHashMap[String, AtomicInteger]
final class ExpensiveMetrics(implicit system: ActorSystem, ec: ExecutionContext) {
import scala.collection.JavaConverters._
private val chm = new ConcurrentHashMap[String, AtomicInteger]().asScala
system.scheduler.schedule(5.seconds, 60.seconds)(publishAllMetrics())
def countRequest(key: String): Unit =
chm.getOrElseUpdate(key, new AtomicInteger(1)).incrementAndGet()
private def resetCount(key: String): Unit =
chm.getOrElseUpdate(key, new AtomicInteger(0)).set(0)
private def publishAllMetrics(): Unit =
chm foreach { case (key, value) =>
// publishMetric(key, value.doubleValue())
resetCount(key)
}
}
以前的实现安全吗?如果没有,在 sn-p 中的什么时候可以引入竞争条件,为什么?
问题的上下文是 AWS CloudWatch 指标,如果在每个请求上发布,这些指标在高频 API 上可能会变得非常昂贵。所以我正在尝试将它们“批处理”并定期发布。
【问题讨论】:
-
相关:How to update a value in a ConcurrentHashMap threadsafe。谈论将 get 和 set 组合成一个原子操作
标签: scala concurrency thread-safety counter scala-collections