SORU
3 Mart 2015, Salı


Özyinelemeli ConcurrentHashMap.() computeİfAbsent asla sona erer. Hata veya "özellik"?

Bir süre önce, I've blogged about a Java 8 functional way of calculating fibonacci numbers recursively, ConcurrentHashMap önbellek ve computeIfAbsent() yeni yararlı yöntemi ile

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);
        });
    }
}

Bu örnek bile daha sofistike bir paralellik sonunda etmedim) tanıtarak yapmayı düşünüyorum çünkü ConcurrentHashMap seçtim.

Şimdi 25 8 sayısını artırmak ve ne olacağını gözlemlemek sağlar

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

Hiçbir zaman program durur. Bu yöntem içinde, sonsuza kadar çalışacak bir döngü var:

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

Kullanıyorum:

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, a reader of that blog post also confirmed the issue (he actually found it).

Bu garip. Aşağıdaki iki birini beklerdim:

  • Çalışıyor
  • ConcurrentModificationException atar

Ama asla durdurma? Bu tehlikeli görünüyor. Bir hata mı? Ya ben bazı sözleşme mi yanlış anladım?

CEVAP
3 Mart 2015, Salı


Bu tabii ki< . em^"" . özellik . ConcurrentHashMap.computeIfAbsent() Javadoc okur:

Eğer belirtilen anahtar zaten bir değeri ile ilişkili olup olmadığını değil, onun değerini hesaplamak için çalışır verilen eşleme işlevini kullanarak ve boş sürece bu harita içine girer. Tüm yöntem çağırma işlevi bir kez anahtar başına en fazla uygulanır yani atomik yapılır. Başka bir iş parçacığı tarafından bu haritada bazı teşebbüs güncelleme işlemleri hesaplama kısa ve basit olmalıdır hesaplama işlemi sırasında bloke olabilirbu harita . başka eşleştirmeleri güncelleştirme girişimi olmamalıdır .

< . em ^"olmamalıdır"ifade algoritmamı eşzamanlılık aynı nedenlerle olmasa da ihlal eden açık bir sözleşmedir.

Hala ilginç ConcurrentModificationException yok. Bunun yerine, program asla hala bence (29 *yani*) oldukça tehlikeli bir böcek olan durur sadece.

Bu somut sorun için kullanın-site basit bir çözüm ConcurrentHashMap ama HashMap sadece bir yerine kullanmak için:

static Map<Integer, Integer> cache = new HashMap<>();

Şimdi, her şey gayet iyi çalışıyor.

Not:

HashMap.computeIfAbsent() Map.computeIfAbsent() Javadoc önbellek türü Map<Integer, Integer>, ConcurrentHashMap<Integer, Integer> değil tabi ki saçma olan bu özyinelemeli hesaplama korusun. Alt büyük ölçüde yeniden tanımlamak süper tip sözleşmeler (Set vs SortedSet tebrik) için çok tehlikelidir.Böylece de süper tür, bu özyineleme gerçekleştirmek için bunun yasak olması gerekir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • akalyne

    akalyne

    13 Mayıs 2009
  • Edgar flores

    Edgar flores

    7 HAZİRAN 2006
  • guau . .

    guau . .

    25 Ocak 2008