<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>