2014-07-15 39 views
2

我正在使用番石榴的高速缓存,并设置了concurrencyLevel1,所以最大容量被利用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 operationsREADs are Lock Free即使concurrencyLevel(1)

我的假设是否正确?


编辑: 我看着番石榴缓存codeand它看起来像我的假设:READs are lock free是正确的。如果是get(K, Callable),它最初会尝试在没有锁定的情况下获取该值,并且如果指定键的条目为null或仅过期,则该条目将用于锁定的Get或Load。如果我在这里错了,请纠正我。

+0

他们如何可能是无锁的,如果你使用的是只有一个分区,而不是整数倍?整个分区点不会增加缓存不同部分的争用。 –

+2

但是为什么文档特别说'允许更新操作之间的并发性'并且没有提及读取操作。我曾认为在这里类似于'ConcurrentHashMap',读取通常是无锁的。 –

回答

4

你可以自己看看代码。大多数相关的东西在LocalCache。我的理解(我不是缓存中的专家),读取(在非LoadingCache上)一般应该是无锁的(在LoadingCache上,它取决于他们是否需要加载一个值在这种情况下,读取也成为写入)。在某些代码路径中,tryLock()用于获取锁定,但由于它是tryLock(),如果锁定被锁定,读取线程不应该被阻塞。我不这么认为。

编辑:

从评论中Segment

段维护始终保持一致的状态条目列出的表,所以可以在不锁定读取。

concurrencyLevel(1)目前指1 Segment

+1

Segment类中的注释声明这些读取是无锁的。 – jtahlborn

+0

@jtahlborn:哦,是的,他们这样做! – ColinD

+0

+1感谢ColinD,是的,我查看了代码,并更新了我的观察结果。 –