【发布时间】:2017-07-03 08:28:03
【问题描述】:
我最近开始在应用程序中使用 Spring 的 @Cacheable 注释来缓存一些昂贵操作的结果。我要替换的代码是广泛使用双重检查锁定模式来确保缓存的一致性和昂贵的例程只执行一次,如下所示:
final String key = SomeClass.computeKey(input)
String cachedValue = mCache.get(key);
if (cachedValue == null) {
synchronized (mCache) {
cachedValue = mCache.get(key);
if (cachedValue == null) {
cachedValue = expensiveComputing(input); // must not be executed twice
mCache.put(key, cachedValue);
}
}
}
上面被替换为:
@Cacheable(value="someCache", key="T(SomeClass).computeKey(#input)")
public String expensiveComputing(Object input) {
// must not be executed twice
}
有时会有第二个缓存来缓存锁定对象以进行实际查找,以避免在计算缓存值期间对整个缓存进行大量同步。
我已经阅读了infinispan's docu on locking,但我仍然想知道我是否需要自己处理这些方面,或者 infinispan 是否可以保证预期的行为。
根据文档 infinispan,从 5.0 开始默认为每个缓存条目创建一个新锁(我使用的是 8.2.6)。那就是锁对象和缓存值的2级缓存应该是不必要的,如果我得到这个正确?!但是双重检查锁定模式呢?这个也可以去掉吗?在高度并发的环境中,expensiveComputing 例程是否仍然只被调用一次?
【问题讨论】:
-
应该不需要那些
synchronized部分。 Infinispan Cache 包含 put if 如果不存在或类似比较和交换的操作,可提供您所需的保证。更准确地说,上面的代码可以只替换为mCache.putIfAbsent。我不是专家,但我不知道 Spring @Cacheable 注释的等价物是什么。我的一位同事或许可以提供帮助。 -
这是正确的方法。请使用
putIfAbsent。 -
@GalderZamarreño,@altanis,不完全是。我需要一个同步的
computeIfAbsent,上面提到的sync标志承诺提供。
标签: java spring caching infinispan