java - Volatile 与并发收集一起使用?

标签 java spring multithreading thread-safety concurrenthashmap

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

  • 混合
  • 最大
  • 柜台
  • timeElapsed[] 等

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

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

我的查询 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);
        }
    }

}

最佳答案

Do i need to make MetricStore variable store volatile?

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

I am using Map as the base class and ConcurrentHashMap as Implemetnation, does it affect as Map is not ThreadSafe

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


这里更大的问题是你在调用 putremove 之前使用了 containsKey 而你应该使用 computecomputeIfPresent,它们是原子操作:

@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);
}

关于java - Volatile 与并发收集一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58345193/

相关文章:

java - 在 JSP 中访问操作 getter

java - 根据选择的单选按钮不同的操作

java - 如何将一个项目作为 Maven 依赖项添加到另一个项目

python - 在后台调用Python函数

php - 爬行抓取和线程?用PHP

java - Java线程池抛出RejectedExecutionException的单元测试

Java在线判断错误解决方法

java - 通过创建 REST 端点使用 spring-boot 发送电子邮件

android - 在 Android 上使用资源所有者密码凭证实现 OAuth2

java - 出现 4** 错误时的 postForEntity 异常