Guava Cache-02 源码阅读之过期键的清理

<code>// 首先从map中取,看看缓存能否命中,是否过期
ReferenceEntry getLiveEntry(Object key, int hash, long now) {
    // 从segment的原子数组中获取kv键值对
    ReferenceEntry e = getEntry(key, hash);
    if (e == null) {
        return null;
    } else if (map.isExpired(e, now)) {
        // 此时仅仅是使用ReentrantLock.tryLock尝试获取锁(CAS方式轻量级获取锁)
        tryExpireEntries(now);
        return null;
    }
    return e;
}

// ReentrantLock.tryLock 非公平锁实现
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        // CAS方式轻量级获取锁,性能开销小
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}


// 如果缓存没有命中
V lockedGetOrLoad(K key, int hash, CacheLoader super K, V> loader)
    throws ExecutionException {
    ReferenceEntry e;
    ValueReference valueReference = null;
    LoadingValueReference loadingValueReference = null;
    boolean createNewEntry = true;

    lock();
    try {     
        long now = map.ticker.read();
        // 占有锁后,进行一次集中的清理
        preWriteCleanup(now); 
        ......
    }
}

// 集中的清理
void runLockedCleanup(long now) {
    if (tryLock()) {
        try {
            // 此处清理软引用与弱引用的键值对
            drainReferenceQueues();
            expireEntries(now); // calls drainRecencyQueue
            readCount.set(0);
        } finally {
            unlock();
        }
    }
}


void expireEntries(long now) {
    // recencyQueue来更新accessQueue元素,保证accessQueue的先进先出逻辑
    drainRecencyQueue();
    ReferenceEntry e;
    while ((e = writeQueue.peek()) != null && map.isExpired(e, now)) {
        if (!removeEntry (e, e.getHash(), RemovalCause.EXPIRED)) {
            throw new AssertionError();
        }
    }
    while ((e = accessQueue.peek()) != null && map.isExpired(e, now)) {
        if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) {
            throw new AssertionError();
        }
    }
}

// 从AtomicReferenceArray,writeQueue、accessQueue这3个数据结构中移除该ntry
boolean removeEntry(ReferenceEntry entry, int hash, RemovalCause cause) {
    int newCount = this.count - 1;
    AtomicReferenceArray> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry first = table.get(index);

    for (ReferenceEntry e = first; e != null; e = e.getNext()) {
        if (e == entry) {
            ++modCount;
            ReferenceEntry newFirst = removeValueFromChain(
                first, e, e.getKey(), hash, e.getValueReference(), cause);
            newCount = this.count - 1;
            // 调整hash数组
            table.set(index, newFirst);
            this.count = newCount; // write-volatile
            return true;
        }
    }

    return false;
}/<code>


分享到:


相關文章: