java - 如何在刷新期间锁定 HashMap ?

标签 java concurrency

我有一个静态的HashMap,它在应用程序启动时填充,并每天刷新。

如何确保刷新期间没有其他线程可以访问 map ?

@ThreadSafe
public class MyService {

   private static final Map<String, Object> map = new HashMap<>();
   private MyDao dao;

   public void refresh(List<Object> objects) {
       map.clear();
       map.addAll(dao.findAll()); //maybe long running routine
   }

   public Object get(String key) {
       map.get(key); //ensure this waits during a refresh??
   }
}

我是否应该引入一个在 refresh() 期间设置和清除的简单 boolean 锁?或者还有更好的选择吗?或者同步机制是一种可行的方法吗?

最佳答案

您可以使用 volatile map 并在填充后重新分配它:

public class MyService {

   private static volatile Map<String, Object> map = new HashMap<>();
   private MyDao dao;

   public void refresh(List<Object> objects) {
       Map<String, Object> newMap = new HashMap<>();
       newMap.addAll(dao.findAll()); //maybe long running routine
       map = newMap;
   }

   public Object get(String key) {
       map.get(key); //ensure this waits during a refresh??
   }
}

它是非阻塞的,从 newMapmap 的分配是原子的并确保可见性:任何后续对 get 的调用都将基于刷新后的 map 。

从性能角度来看,这应该可以很好地工作,因为 volatile 读取几乎与正常读取一样快。 volatile 写入稍微慢一点,但考虑到刷新频率,这应该不是问题。如果性能很重要,您应该运行适当的测试。

注意:您必须确保没有外部代码可以访问 map 引用,否则该代码可能会访问过时的数据。

关于java - 如何在刷新期间锁定 HashMap ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28147889/

相关文章:

mysql - 按 id 排序的复合索引的并发查询速度非常慢

java - 创建 Eclipse SVN "virtual branches"?

java - Android MainDexClassList 构建错误

java - 从网络接收一个对象并区分它

java - 在 Android 上的所有应用中添加 KeyListener 和 Draw To Screen

c# - 更新 ConcurrentDictionary 中的值字段

java - 计算 ZIP 目录中的文件 - JAVA、Android

应用 java AtomicIntegeraccumulateAndGet

database - Django 原子检查和递减

concurrency - 应用程序对象和并发问题