以下代码线程安全吗? 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");
}
}
答案 0 :(得分:3)
使用ConcurrentHashMap
和computeIfAbsent
纠正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));
}
请注意,编写起来也更简单。