Rekursive ConcurrentHashMap.computeIfAbsent () - Aufruf nie beendet. Bug oder "feature"?

Einige Zeit her, Gebloggt habe ich über einen Java 8 funktionale Art und Weise der Berechnung der fibonacci-zahlen rekursiv, mit einem ConcurrentHashMap cache und die neue, nützliche computeIfAbsent() Methode:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {
    static Map<Integer, Integer> cache = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        System.out.println(
            "f(" + 8 + ") = " + fibonacci(8));
    }

    static int fibonacci(int i) {
        if (i == 0)
            return i;

        if (i == 1)
            return 1;

        return cache.computeIfAbsent(i, (key) -> {
            System.out.println(
                "Slow calculation of " + key);

            return fibonacci(i - 2) + fibonacci(i - 1);
        });
    }
}

Wählte ich ConcurrentHashMap weil ich dachte, dieses Beispiel noch raffinierter durch die Einführung von Parallelität (was ich nicht am Ende).

Nun vergrößern wir die Anzahl von 8 zu 25 und beobachten, was passiert:

        System.out.println(
            "f(" + 25 + ") = " + fibonacci(25));

Das Programm nie unterbrochen. Innerhalb der Methode gibt es eine Schleife, die läuft einfach immer:

for (Node<K,V>[] tab = table;;) {
    //...
}

Ich bin mit:

C:\Users\Lukas>java -version
java version "1.8.0_40-ea"
Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b23)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

Matthias, ein Leser von diesem blog-post auch bestätigt das Problem (er fand es sogar).

Dies ist seltsam. Ich hätte erwartet, dass eine der folgenden zwei:

  • Es funktioniert
  • Es wirft ein ConcurrentModificationException

Aber eben nie aufzuhalten? Das scheint gefährlich. Ist es ein bug? Oder habe ich missverstanden, einige Vertrag?

InformationsquelleAutor Lukas Eder | 2015-03-03
Schreibe einen Kommentar