我正在使用Guava的缓存,并将concurrencyLevel
设置为1
,因此w.r.t使用了最大容量。驱逐令人担忧。以下是我的代码:
CacheBuilder.newBuilder()
.maximumWeight(maxWeight)
.concurrencyLevel(1)
.expireAfterWrite(expireDuration, TimeUnit.MINUTES)
.removalListener(new RemovalListener<K, V>() {
@Override
public void onRemoval(RemovalNotification<K, V> removalNotification) {
log.warn(removalMsg + removalNotification.getKey());
}
})
.weigher(weigher)
.build();
concurrencyLevel的文档说明了这一点:
指导更新操作中允许的并发性。用作提示 用于内部尺寸。该表在内部分区以尝试 允许指定数量的并发更新而不用 争...
因此我假设concurrencyLevel
仅对update operations
和READs are Lock Free
的角色扮演角色,即使只有concurrencyLevel(1)
。
我的假设是否正确?
修改
我查看了Guava缓存代码,看起来我认为READs are lock free
是正确的。如果get(K, Callable)
最初尝试获取没有锁定的值,并且如果指定键的条目为空或仅已过期,那么它将用于锁定的Get或Load。如果我在这里错了,请纠正我。
答案 0 :(得分:4)
您可以自己查看代码。大部分相关内容都在LocalCache
。
无论如何,根据我的理解(我不是缓存内容的专家),读取(在非LoadingCache
上)通常应该是无锁的(在LoadingCache
上取决于他们是否需要加载一个值,在这种情况下,读取也成为一个写入。在某些代码路径中,tryLock()
用于获取锁定,但由于它tryLock()
没有读取线程,因此如果锁定被锁定则不应该阻止我认为。
修改强>
来自Segment
的评论:
细分维护一个条目表列表,这些条目列表始终保持一致状态,因此可以在不锁定的情况下读取。
(concurrencyLevel(1)
目前表示1 Segment
。)