仔细检查HashMap上的锁定-线程安全吗?

时间:2018-10-16 21:51:04

标签: java multithreading concurrency locking

以下代码线程安全吗? SlidingTimeWindowCountGauge类已经是线程安全的。问题在于双重检查锁定代码和常规的非并行哈希图。

我想在哈希图中延迟创建条目。条目只能创建一次,然后再使用。我想尽可能避免锁定。

public class InstrumentedCaller {
    private final Map<String, SlidingTimeWindowCountGauge> nameToCountGauge = new HashMap<>();

    private SlidingTimeWindowCountGauge getGaugeLazy(final String name) {
        SlidingTimeWindowCountGauge gauge = nameToCountGauge.get(name);
        if (gauge != null) {
            return gauge;
        }
        synchronized (this) { 
            if (nameToCountGauge.containsKey(name)) { 
                return nameToCountGauge.get(name);
            }
            final SlidingTimeWindowCountGauge newGauge = new SlidingTimeWindowCountGauge(1, TimeUnit.MINUTES);
            this.nameToCountGauge.put(name, newGauge);
            return newGauge;
        }
    }

    private void markCall(final String callName) {
        SlidingTimeWindowCountGauge gauge = getGaugeLazy(callName);
        gauge.mark();
    }

    public void doCall1() {
       markCall("call1");
    }

    public void doCall2() {
       markCall("call2");
    }
}

1 个答案:

答案 0 :(得分:3)

使用ConcurrentHashMapcomputeIfAbsent纠正getGaugeLazy的线程安全实现:

private final Map<String, SlidingTimeWindowCountGauge> nameToCountGauge = new ConcurrentHashMap<>();

private SlidingTimeWindowCountGauge getGaugeLazy(final String name) {
    return nameToCountGauge.computeIfAbsent(name, k -> new SlidingTimeWindowCountGauge(1, TimeUnit.MINUTES));
}

请注意,编写起来也更简单。