Search code examples
javaguava

guava cache containsValue


public boolean containsValue(@Nullable Object value) {
    if (value == null) {
        return false;
    }
    long now = ticker.read();
    final Segment<K, V>[] segments = this.segments;
    long last = -1L;
    for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) {
        long sum = 0L;
        for (Segment<K, V> segment : segments) {
            // ensure visibility of most recent completed write
            int unused = segment.count; // read-volatile

            AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
            for (int j = 0; j < table.length(); j++) {
                for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) {
                    V v = segment.getLiveValue(e, now);
                    if (v != null && valueEquivalence.equivalent(value, v)) {
                        return true;
                    }
                }
            }
            sum += segment.modCount;
        }
        if (sum == last) {
            break;
        }
        last = sum;
    }
    return false;
}

there is the containsValue mathed.My question is that why only check modCount when not found the value.if other thread invoke the remove operation before 'return true',this mathed will be wrong.forgive my poor English.


Solution

  • Yes, this can race. So can any operation using the result of containsValue; but if it returns true, then the value was present at some point while the method was being evaluated; that's the best you could possibly do anyway.

    As far as modCount goes, that's only being used if the value isn't present because it's used to detect if the map is being concurrently modified and it needs to look again. But if the value was present at any time during the iteration, then the method should return true, which it does.