【发布时间】:2022-01-10 14:36:39
【问题描述】:
我发现使用 CacheLoader 的 put 和 get 操作在后台使用 Reentrant 锁,但为什么 getIfPresent 操作没有实现呢?
getIfPresent 使用的get
@Nullable
V get(Object key, int hash) {
try {
if (this.count != 0) {
long now = this.map.ticker.read();
ReferenceEntry<K, V> e = this.getLiveEntry(key, hash, now);
Object value;
if (e == null) {
value = null;
return value;
}
value = e.getValueReference().get();
if (value != null) {
this.recordRead(e, now);
Object var7 = this.scheduleRefresh(e, e.getKey(), hash, value, now, this.map.defaultLoader);
return var7;
}
this.tryDrainReferenceQueues();
}
Object var11 = null;
return var11;
} finally {
this.postReadCleanup();
}
}
放
@Nullable
V put(K key, int hash, V value, boolean onlyIfAbsent) {
this.lock();
.....
为了在基本的 get/put 操作中实现线程安全,我唯一能做的就是在客户端上使用同步吗?
【问题讨论】:
-
独占访问需要锁定才能进行修改。一次读取可以作为内存屏障来查看最新值,因此它可以是无锁的,以避免多个读取器导致争用的成本。这需要特别小心,以免读者看到多个字段的部分写入(例如corrupted list walk)。同样
ConcurrentHashMap做同样的事情,get(key)没有被并发调用put(key, value)阻塞。这是性能优化。