使用 ConcurrentHashMap 的线程安全

Threadsafe with ConcurrentHashMap

我有一个问题,我需要在多线程环境中最多 运行 .register 一次,所以我尝试使用 ConcurrentHashMap 但似乎它不是线程安全的或我正在正确使用它

object NonFunctionalMetrics {

  val histograms = new ConcurrentHashMap[String, Histogram](10).asScala
  def workerProcessingHistogram(name: String): Histogram = {
    val histogramName = s"${prefix}_${name.toSnakeCase}_processing_time"
    histograms.getOrElseUpdate(
                              key = histogramName,
                              op = Histogram.build(histogramName, s"${name} worker processing time in microseconds")
                                .labelNames("status")
                                .linearBuckets(config.service.metrics.http.histogramStart, config.service.metrics.http.histogramWidth, config.service.metrics.http.histogramCount)
                                .register()
    )
  }
}

抛出异常

Collector already registered that provides name: my_app_new_site_exclusion_worker_processing_time_count

于:

    val onSuccessHistogram: Histogram.Child = NonFunctionalMetrics.workerProcessingHistogram(worker.name).labelSuccess()
    val onFailureHistogram: Histogram.Child = NonFunctionalMetrics.workerProcessingHistogram(worker.name).labelFailure()

当我添加 synchronized 它的工作伟人时,如下所示:

 def workerProcessingHistogram(name: String): Histogram = synchronized {
    val histogramName = s"${prefix}_${name.toSnakeCase}_processing_time"
    histograms.getOrElseUpdate(
                              key = histogramName,
                              op = Histogram.build(histogramName, s"${name} worker processing time in microseconds")
                                .labelNames("status")
                                .linearBuckets(config.service.metrics.http.histogramStart, config.service.metrics.http.histogramWidth, config.service.metrics.http.histogramCount)
                                .register()
    )
  }

我看到 get(key) 两个线程正在获得 false 答案并使用 register 创建直方图 - ConcurrentHashMap 不需要处理这些场景吗?

您可以在基础 Java ConcurrentHashMap 上使用 computeIfAbsent。但是 .asScala 返回的 ConcurrentMap 上的 getOrElseUpdate 将使用 Scala 中可变 Map 的 non-concurrent 实现。