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