2013-11-21 11 views
7
Uygulama Java eşzamanlılık olarak

, sayfa 106, bu Memoizer3 sorunun [iki konu boş görerek ve pahalı hesaplama başlangıç] bir bileşik eylem (koyun-if-devamsızlık) arka harita üzerinde gerçekleştirilir çünkü karşı savunmasız olduğunu "söylüyor olamaz kilitleme kullanılarak atomik yapılmalıdır. " Neden kilitlemeyi kullanarak atom yapamadığını söylediklerini anlamıyorum. İşte orjinal kod:Neden Java Concurrency Uygulama Davranışları 5.18'de atomik kilitli olarak yapılıyor?

Neden böyle bir şey işe yaramaz? Tabii

... 
public V compute(final A arg) throws InterruptedException { 
    Future<V> f = null; 
    FutureTask<V> ft = null; 
    synchronized(this){ 
     f = cache.get(arg); 
     if (f == null) { 
      Callable<V> eval = new Callable<V>() { 
       public V call() throws InterruptedException { 
        return c.compute(arg); 
       } 
      }; 
      ft = new FutureTask<V>(eval); 
      f = ft; 
      cache.put(arg, ft);     
     } 
    } 
    if (f==ft) ft.run(); // call to c.compute happens here 
    ... 

cevap

1

It kilitleme kullanarak atomik yapılabilir, en ilkel durumda düşünün: Eğer tüm fonksiyon etrafında küresel bir kilit var, sonra her şey tek iş parçacıklı ve bu nedenle iş parçacığı güvenlidir. Sanırım ya başka bir şey ifade ettiler ya da genel bir yanlış anlaşılma vardı.

Kişisel kodu da böyle ConcurrentHashMap arasında putIfAbsent yöntemi kullanılarak geliştirilebilir:

public V compute(final A arg) throws InterruptedException { 
    Future<V> f = cache.get(arg); 
    if (f == null) { 
    final Callable<V> eval = new Callable<V>() { 
     public V call() throws InterruptedException { 
     return c.compute(arg); 
     } 
    }; 
    final FutureTask<V> ft = new FutureTask<V>(eval); 
    final Future<V> previousF = cache.putIfAbsent(arg, ft); 
    if (previousF == null) { 
     f = ft; 
     ft.run(); 
    } else { 
     f = previousF; // someone else will do the compute 
    } 
    } 
    return f.get(); 
} 

f ucunda en, arasında veya ilk değer ilave edilmiş bir önceki değeri olur, ya Bir Callable'ın fazladan yaratılmasının potansiyel maliyeti, ancak hesaplama için bir defadan fazla çağrı yapılmaz.

+0

Evet, yazarlar metinde bir putIfAbsent çözümü verir. – PeteyPabPro