2013-06-18 13 views
7

Aşağıda, Etkili Java 2. Edition'ın snippet'i bulunmaktadır. Burada yazar, aşağıdaki kod parçasının, sonuç değişkenini kullanmadığınızdan% 25 daha hızlı olduğunu iddia ediyor. "Bu değişkenin yaptığı şey, alanın önceden başlatılmış olduğu ortak durumda yalnızca bir kez okunmasını sağlamaktır." . Yerel değişken sonucunu kullanmıyorsak, bu kodun değer sıfırlanmasından sonra neden bu kadar hızlı olacağını anlayamıyorum. Her iki durumda da, yerel değişken sonucunu kullanıp kullanmadığınızı, başlattıktan sonra sadece bir uçucu okunacaksınız.Neden çift kilitleme, Joshua Bloch'da% 25 daha hızlıdır Etkili Java Örneği

if (field == null) {...} 
return field; 

ya: field kez

// Double-check idiom for lazy initialization of instance fields 
private volatile FieldType field; 

FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
      result = field; 
      if (result == null) // Second check (with locking) 
       field = result = computeFieldValue(); 
     } 
    } 
    return result; 
} 
+1

Uhm, bu ilk baskısı mı? Çifte kontrol edilen kilitleme birkaç yıldan beri vazgeçilmiştir – fge

+0

Ve nedeni: http://stackoverflow.com/questions/4926681/why-is-double-checked-locking-broken-in-java?rq=1 – Lenymm

+4

@fge : Pek sayılmaz. Java 5, bu yana aslında bir OK kalıbı: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html –

cevap

6

kod ya olduğunu başlatıldı oluşturuldu.Müzik uçucu değişken okumak İlk durumda

result = field; 
if (result == null) {...} 
return result; 

iki kez oysa ikinci yalnızca bir kez oku. Uçucu okumalar çok hızlı olmasına rağmen, yerel değişkenlerden okumaktan biraz daha yavaş olabilirler (% 25 olup olmadığını bilmiyorum).

Notlar:

  • uçucu okur son işlemci (en azından 86)/JVMs, yani hiçbir fark yoktur okur, normal olarak ucuz.
  • Ancak derleyici, kodları daha iyi optimize edebilir, böylece daha iyi derlenmiş kodlardan verimlilik elde edebilirsiniz.
  • Birkaç nanosaniyenin% 25'i hala çok fazla değil.
  • Eğer java.util.concurrent paketinin birçok sınıflarında bulabilirsiniz standart bir deyim - örneğin this method in ThreadPoolExecutor için (bkz vardır birçoğu) en çağrılardan içinde, yerel bir değişken kullanmak olmadan
+0

tamam demek ki "geri dönüş alanı" da bir uçucu okumayı (sağlanmış alan uçucu) oluşturur – veritas

+0

@veritas Evet öyle - bayt kodu incelerseniz, iade edilmeden önce yüklendiğini göreceksiniz. – assylias

+0

ok teşekkürler @assylias – veritas

0

Elimizdeki etkili bir

if(field!=null) // true 
    return field; 

yüzden daha yavaş bir uçucu okuma olan uçucu iki okur vardır. Aslında, JVM, iki uçucu okumayı bir uçucu okumaya birleştirebilir ve yine de JMM'ye uyumlu olabilir. Ancak, JVM'nin her seferinde söylendiğine göre iyi bir inanç oynamasını beklediğini, bir kargaşa olmayacağını ve herhangi bir uçucu okumayı en iyi duruma getirmeye çalışacağını umuyoruz. Biz JVM gerçekten defalarca değişkeni yüklenmesini istiyor bu kodu

volatile boolean ready; 

do{}while(!ready); // busy wait 

düşünün.

İlgili konular