дважды проверить блокировку на HashMap - потокобезопасен? - PullRequest
0 голосов
/ 17 октября 2018

Безопасен ли следующий поток кода?Класс 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 голосов
/ 17 октября 2018

Корректная поточно-ориентированная реализация getGaugeLazy с использованием ConcurrentHashMap и computeIfAbsent:

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

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

Обратите внимание, что также намного прощенаписать.

...