[英]How to update a LinkedList value stored in cache using Guava's LoadingCache
[英]Putting a value in a google guava loadingCache
这是我的加载缓存定义:
private class ProductValue {
private long regionAValue;
private long regionBValue;
// constructor and general stuff here
}
private final LoadingCache<ProductId, ProductValue> productCache = CacheBuilder.newBuilder()
.expireAfterAccess(4, TimeUnit.MINUTES)
.build(new CacheLoader<ProductId, ProductValue>() {
@Override
public ProductValue load(final ProductId productId) throws Exception {
return updateProductValues(productId);
}
});
private ProductValue updateProductValues(final ProductId productId) {
// Read from disk and return
}
现在,我有一个用例,需要在高速缓存中设置regionA或regionB的值,直到下一次更新发生为止。 我对自己所具有的逻辑的并发含义感到困惑:
public void setProductValue(final ProductId productId, final boolean isTypeA, final long newValue) throws ExecutionException {
ProductValue existingValues = productCache.get(productId); // 1
if (isTypeA) {
existingValues.regionAValue = newValue;
} else {
existingValues.regionBValue = newValue;
}
productCache.put(productId, existingValues); // 2
}
在1
我只是读取了给定密钥存储在缓存中的信息的引用,此get是线程安全的,因为加载缓存的行为类似于并发映射。 但是在1
和2
之间,此引用可以被其他一些线程覆盖。 由于我已经使用缓存中已经存在的引用覆盖了“值”,因此是否需要将键值对放入缓存中? 我是否需要行2
?
(免责声明:我不是Guava Cache专家)
我认为您的代码中存在两个并发问题:
existingValues.regionAValue = ...
值existingValues.regionAValue = ...
和existingValues.setRegionValue(...)
。 当仅应用一个操作时,其他线程可以看到状态。 我认为这是不想要的。 (正确?) get()
和put()
该值可能会再次加载到缓存中,而put()
覆盖一个新值。 关于1:
如果对对象的读取多于写入,那么一个好的选择是使用不可变的对象。 您无需触摸实例,但可以复制原始对象,进行变异,然后将新对象放入缓存中。 这样,只有最终状态才可见。
关于2:
原子CAS操作可以为您提供帮助(例如,兼容JSR107的缓存)。 有用的方法是布尔值替换(K键,V oldValue,V newValue);
在Google Guava中,可以通过ConcurrentMap接口访问CAS方法,您可以通过asMap()进行检索。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.