【问题标题】:Thread safe swap of entire map in JavaJava中整个地图的线程安全交换
【发布时间】:2022-01-24 16:20:06
【问题描述】:

我正在 Spring Web 服务中实现线程安全的 map

地图是这样的。

  • 在数千个客户端线程中同时读取地图。
  • 有时必须完全更新地图的内容(大约每小时一次)。

我已选择 ConcurrentHashMap 用于线程安全映射,但没有功能可以简单地将其内容与较新的映射交换,例如 c++ 中的 std::map::swap()
(我以为多线程环境需要对整个内容进行原子更新,也许我错了)

有没有swap的替代地图?

任何建议或回复将不胜感激。谢谢。

【问题讨论】:

  • 在这种情况下,为什么不直接指向新地图呢?请记住让您的实例变量为 volatile,以便所有线程都在查看最新的地图。
  • @AminM 我没想到。也许在我的情况下是可能的,我会试试看。
  • AtomicReference 可能会更好,因为他们建议如下。
  • 只需要一个 volatile 变量。 AtomicReference get/set 只是 volatile get/set。所以我什至不会打扰 AtomicReference。

标签: java multithreading concurrenthashmap


【解决方案1】:

如果不需要改变地图,只需原子地替换它,您可以将地图包装在AtomicReference 中,然后原子地替换引用中的引用单去。不同的线程不会保留对地图实例本身的引用,而是对周围的AtomicReference 实例的引用。

class Example {
    private final AtomicReference<Map<String, String>> mapRef = new AtomicReference<>(someInitialState);

    private void consumerThread() {
        // Get the current version of the map and look up a value from it.
        String value = mapRef.get().get("Hello");
        // Do something with value.
    }

    private void producerThread() {
        // Time to replace the whole map for all threads
        Map<String, String> newMap = calculateNewMap();
        mapRef.set(newMap);
    }
}

【讨论】:

  • 我已经阅读了AtomicReference 的内部代码,并意识到AtomicReference.get()AtomicReference.set() 只是等于赋值运算符(=)。与简单的= 运算符有什么区别吗?
  • 这是关于“java atomicreference 与同步”stackoverflow.com/questions/28834489/… 的一个很好的阅读材料,它同意因为您想编辑一个字段,所以 AtomicReference 是更好的选择。更好的是使整个事物不可变,但这似乎不是一个选择。
  • @codingmonster, Re, "...等于赋值运算符。"只要确保您了解分配的内容!变量AtomicReference ar 本身就是对AtomicReference 对象的引用,当您调用ar.set(...) 时,您实际上是在分配给该对象的volatile 字段。这就像你在写ar.value = ...,而不是你在写ar = ...
  • @SolomonSlow 我的意思是ConcurrentHashMap mp; mp = ...,而不是AtomicReference ar; ar =...。当我将ar 声明为AtomicReference&lt;ConcurrentHashMap&lt;String, Object&gt;&gt; ar = new AtomicReference&lt;&gt;(mp); 时,ar.value 等于mp
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多