source

Oracle Java ConcurrentHashMap의 잘못된 구현?

lovecheck 2023. 7. 26. 22:10
반응형

Oracle Java ConcurrentHashMap의 잘못된 구현?

Oracle의 Java 8 구현을 테스트 중입니다.

ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<>();
String result = concurrentMap.computeIfAbsent("A", k -> "B");
System.out.println(result);  // "B"
result = concurrentMap.putIfAbsent("AA", "BB");
System.out.println(result);  // null

자바독은 그렇게 말합니다.

구현 요구 사항:

기본 구현은 이 맵에 대한 다음 단계와 같으며, 현재 값이 없으면 null을 반환합니다.

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null)
        return map.putIfAbsent(key, newValue);
}

그러면 현재 값을 반환하거나 현재 없으면 null을 반환한다고 합니다.그래서 그것은 돌아올 것입니다.null 점을 하면,putIfAbsent또한 돌아오고 있습니다.null.

내가 여기서 뭘 놓쳤지요?

ConcurrentMap.computeIfAbsent실제 의도를 반영하지 않고 있습니다. 대부분의 경우 비폭력적인 행동으로 인한 실수일 가능성이 높습니다.putIfAbsent구현이 문서화된 의도를 따르는 동안.이 문제는 JDK-8174087에서 보고되었으며 Java 9에서 해결되었습니다.

에 대한 계약은 다음과 같습니다.

구현 요구 사항:

기본 구현은 이 맵에 대한 다음 단계와 같으며, 현재 값이 없으면 null을 반환합니다.

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null)
        map.put(key, newValue);
}

략생을 return진술.하지만 분명히 말하지만,

반환:

지정된 키와 연결된 현재(기존 또는 계산된) 값 또는 계산된 값이 null인 경우 null

이것은 동시성 측면을 통합하려고 시도하는 문서이며, 다음의 비직관적인 행동에 속합니다.putIfAbsent:

구현 요구 사항:

기본 구현은 이 맵에 대한 다음 단계와 같으며, 현재 값이 없으면 null을 반환합니다.

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null)
        return map.putIfAbsent(key, newValue);
}

하지만 여전히 그것은 말합니다.

반환:

지정된 키와 연결된 현재(기존 또는 계산된) 값 또는 계산된 값이 null인 경우 null

그리고 문서화된 의도는 코드 예제보다 우선되어야 합니다.의 실제 구현은 문서화된 의도와 일치합니다.

@Override
default V computeIfAbsent(K key,
        Function<? super K, ? extends V> mappingFunction) {
    Objects.requireNonNull(mappingFunction);
    V v, newValue;
    return ((v = get(key)) == null &&
            (newValue = mappingFunction.apply(key)) != null &&
            (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
}

따라서이행은 두 가지 모두의 문서화된 의도에 부합합니다.ConcurrentMap.computeIfAbsent그리고.Map.computeIfAbsent반환된 값과 관련하여 또한 다음과 같습니다.default인터페이스에 의해 제공되는 구현.

전성을위해완,,default의 구현

default V computeIfAbsent(K key,
        Function<? super K, ? extends V> mappingFunction) {
    Objects.requireNonNull(mappingFunction);
    V v;
    if ((v = get(key)) == null) {
        V newValue;
        if ((newValue = mappingFunction.apply(key)) != null) {
            put(key, newValue);
            return newValue;
        }
    }

    return v;
}

javadoc의 실제 코드:

 if (map.get(key) == null) {
 V newValue = mappingFunction.apply(key);
     if (newValue != null)
         map.put(key, newValue);  // <-
     }
 }

보시다시피 없습니다.return키워드를 입력합니다.

섹션 "return"에도 다음이 표시됩니다.

반환: 지정한 키와 연결된 현재(기존 또는 계산된) 값 또는 계산된 값이 null인 경우 null을 반환합니다.

언급URL : https://stackoverflow.com/questions/46272108/wrong-implementation-of-oracle-java-concurrenthashmap

반응형