code: private void evictIfOverLimit() {
      int numToEvict = mCache.size() - mSoftLimit;
  
      if (numToEvict <= 0) {
        return;
      }
  
      if (mEvictLock.tryLock()) {
        try {
          // update the total number to evict while we are holding the lock
          numToEvict = mCache.size() - mSoftLimit;
          // This thread won the race as the evictor
          while (numToEvict > 0) {
            if (!mIterator.hasNext()) {
              mIterator = mCache.entrySet().iterator();
            }
            Map.Entry<K, ValNode> candidateMapEntry = mIterator.next();
            ValNode candidate = candidateMapEntry.getValue();
            if (candidate.mIsAccessed) {
              candidate.mIsAccessed = false;
            } else {
              if (candidate.mRefCount.compareAndSet(0, Integer.MIN_VALUE)) {
                // the value object can be evicted, at the same time we make refCount minValue
                mIterator.remove();
                numToEvict--;
              }
            }
          }
        } finally {
          mEvictLock.unlock();
        }
      }
    }
docs: If the size of the cache exceeds the soft limit and no other thread is evicting entries,
  start evicting entries.