From b824a6ea055cd4ff5e06df6fa01758e846d1d413 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 22 Mar 2014 14:57:12 +0000 Subject: [PATCH] Tweak to support finer grained locking Fixes gh-543 --- .../metrics/writer/CodahaleMetricWriter.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CodahaleMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CodahaleMetricWriter.java index 9502f6b282..d79a150717 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CodahaleMetricWriter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CodahaleMetricWriter.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.metrics.writer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import org.springframework.boot.actuate.metrics.Metric; @@ -49,6 +51,8 @@ public class CodahaleMetricWriter implements MetricWriter { private final MetricRegistry registry; + private final ConcurrentMap gaugeLocks = new ConcurrentHashMap(); + /** * Create a new {@link CodahaleMetricWriter} instance. * @param registry the underlying metric registry @@ -86,13 +90,19 @@ public class CodahaleMetricWriter implements MetricWriter { } else { final double gauge = value.getValue().doubleValue(); + Object lock = null; + if (this.gaugeLocks.containsKey(name)) { + lock = this.gaugeLocks.get(name); + } + else { + this.gaugeLocks.putIfAbsent(name, new Object()); + lock = this.gaugeLocks.get(name); + } - // ensure we synchronize on the registry to avoid another thread - // pre-empting this thread after remove causing register to be - // called twice causing an error in CodaHale metrics - // NOTE: this probably should not be synchronized, but CodaHale - // provides no other methods to get or add a particular gauge - synchronized (this.registry) { + // Ensure we synchronize to avoid another thread pre-empting this thread after + // remove causing an error in CodaHale metrics + // NOTE: CodaHale provides no way to do this atomically + synchronized (lock) { this.registry.remove(name); this.registry.register(name, new SimpleGauge(gauge)); }