首页 > 解决方案 > 与并发收集一起使用的易失性?

问题描述

我正在开发一个指标存储(Map),它基本上收集有关某些操作的指标,例如

这里 Key 是方法的名称, value 是关于它的指标。

Spring 可以帮助我创建MetricStore的单例对象,当多个 REST 请求并行出现时,我正在使用ConcurrentHashMap来避免竞争条件。

我的查询 1- 我需要使 MetricStore 变量存储易失吗?提高多个请求之间的可见性。2-我使用 Map 作为基类,使用 ConcurrentHashMap 作为实现,它是否会影响 Map 不是 ThreadSafe。-

@Component
class MetricStore{
    public Map<String, Metric> store = new ConcurrentHashMap<>();
    //OR  public volatile Map<String, Metric> store = new ConcurrentHashMap<>();
}

@RestController
class MetricController{
    @Autowired
    private MetricStore metricStore;

    @PostMapping(name="put")
    public void putData(String key, Metric metricData) {
        if(metricStore.store.containsKey(key)) {
            // udpate data
        }
        else {
            metricStore.store.put(key, metricData);
        }
    }

    @PostMapping(name="remove")
    public void removeData(String key) {
        if(metricStore.store.containsKey(key)) {
            metricStore.store.remove(key);
        }
    }

}

标签: javaspringmultithreadingthread-safetyconcurrenthashmap

解决方案


我需要使 MetricStore 变量存储易失吗?

不,因为您没有更改 的值store(即store可以标记为final并且代码仍应编译)。

我使用 Map 作为基类,使用 ConcurrentHashMap 作为实现,它是否会影响 Map 不是 ThreadSafe

因为您使用 aConcurrentHashMap作为 的实现Map,所以它是线程安全的。如果您希望声明的类型更具体,Map可以更改为ConcurrentMap.


这里更大的问题是您containsKey在调用之前使用put以及remove何时应该使用computeand computeIfPresent,这是原子操作:

@PostMapping(name="put")
public void putData(String key, Metric metricData) {
    metricStore.store.compute(key, (k, v) -> {
        if (v == null) {
            return metricData;
        }

        // update data
    });
}

@PostMapping(name="remove")
public void removeData(String key) {
    metricStore.store.computeIfPresent(key, (k, v) -> null);
}

推荐阅读