【发布时间】:2011-03-15 02:53:19
【问题描述】:
我有一个使用简单 HashMap 实现的缓存。喜欢-
HashMap<String,String> cache = new HashMap<String,String>();
此缓存大部分时间用于从中读取值。我有另一种重新加载缓存的方法,在这个方法内部,我基本上创建了一个新的缓存,然后分配引用。据我了解,对象引用的分配在 Java 中是原子的。
public class myClass {
private HashMap<String,String> cache = null;
public void init() {
refreshCache();
}
// this method can be called occasionally to update the cache.
public void refreshCache() {
HashMap<String,String> newcache = new HashMap<String,String>();
// code to fill up the new cache
// and then finally
cache = newcache; //assign the old cache to the new one in Atomic way
}
}
我了解,如果我不将缓存声明为 volatile,其他线程将无法看到更改,但我的用例将缓存中的更改传播到其他线程并不是时间关键,它们可以继续工作长时间使用旧缓存。
您是否发现任何线程问题?考虑到许多线程正在从缓存中读取数据,并且只是有时会重新加载缓存。
编辑- 我的主要困惑是我不必在这里使用 AtomicReference,因为赋值操作本身是原子的?
编辑 - 我知道为了使排序正确,我应该将缓存标记为易失性。 但是如果 refreshCache 方法被标记为已同步,我不必将缓存设置为 volatile,因为同步块将负责排序和可见性?
【问题讨论】:
-
为了简单的缓存目的,我通常使用 ConcurrentHashMap 并且不用担心锁定。我通常不在乎(引用透明的)计算是否发生两次(比如说因为线程 B 开始计算与线程 A 当前正在计算的值相同的值,因此还没有放入缓存中)。在你的情况下,我也会将 cache 设为 volatile。但我没有看到“刷新缓存”的意义。让你的缓存成为 LRU/MRU,然后简单地向它添加新的缓存值,而不是“重置”它。
-
至少使用新映射刷新缓存允许使用非阻塞缓存映射实现
标签: java multithreading