2011-08-13 12 views
10

Bir kullanıcının bir int döndüren bir yöntem eşitler düşünelim:Java, gereksiz senkronize ifadeleri kaldırır/optimize eder mi?

int whatever = 33; 
... 

public synchronized int getWathever() { 
    return this.whatever; 
} 

Biz int atomik değiştirilmiş Java özellikleri biliyoruz. Bu nedenle, synchronized ifadesi gerekli değildir.

Derleyiciler onu kaldıracak/optimize edecekler mi?

+2

Şüpheli. Eğer siz (programcı) bunu gereksiz olarak tanımanızda neden kodda belirtin? – Hyperbole

+2

Yapmayacağım, ama 3. taraf koduna ya da kendime yazmadığım kodlara bağlı olduğumu varsayalım. – JVerstry

cevap

7

Hayır alarak sağlamak için en kolay yoldur değişkenin yükleme sırasında herhangi bir başka iş parçacığı tarafından tutulan değildir temin etmelidir bile. Derleyici ve JVM bunu yapsaydı, Java programlama dili bellek modeli tarafından belirlenen kısıtlamaların ihlal edilmiş olması muhtemeldir. Daha fazla özellikle, Java Dil Özellikleri'nde belirtilen synchronization order siparişi ihlal edilir. Bir derleyici veya bir JVM * herhangi bir "istenmeyen" eşitlemeyi kaldırsaydı, daha sonra yapılan herhangi bir ek optimizasyon, bir geliştirici tarafından senkronizasyon sırasına (ve önce-önce) ilişkisine yerleştirilen varsayımları ihlal eder. Özel durumunuzda, tamsayıya yazma işlemi, Java bellek modeline uyan bir derleyici/JVM'de okunmadan önce olur.

Senkronizasyonları kaldıran bir derleyici/JVM, bellek modelinin ihlal edildiği bir ortamla sonuçlanabilir. Örneğin, astar içi yöntem, tamsayı değerinin okunmasından önce bir bellek bariyerini yerleştiren derleyici/JVM olmadan gerçekleştirilebilir, böylece eski değerlerin önbelleğe alınmış bir değerden okunmasına izin verilir.

* Not: Derleyici/JVM duo referansı kasıtlıdır. Bir derleyici yalnızca JLS ile uyumlu olan bayt kodu gönderir; Bir JVM, bellek modelinin gereksinimlerinin hala ihlal edilebileceği bir hatayı alabilir. Bellek modelinin bütünlüğü için, hem derleyici hem de JVM, bellek modeli tarafından belirlenen gereksinimlere uygun olmalıdır.

+0

Bu cevap temel olarak çıngırak ucunun biriyle aynı olsa da, bence davranışı daha net hale getiriyor - +2 verebilir miyim? – Voo

+0

HotSpot 1.6'dan beri mümkündür. Ancak Java derleyicisi tarafından değil JIT derleyicisi tarafından kaldırılır. Tek bir iş parçacığında kullanıldıkları takdirde, StringBuffer veya Hashtab'de 'StringBuilder' veya HashMap'de gereksiz senkronizasyonun neden olduğu performans cezasının, HotSpot JVM 1.6'dan beri minimum düzeyde olduğu belgelenmiştir. Bkz. Http://www.ibm.com/developerworks/java/library/j-jtp10185/ – Oliv

4

Eğer int değişkeninin başka bir şekilde ana bellekle düzgün bir şekilde senkronize olduğundan emin olmadıkça, bu iş parçacığı güvenli bir hale getirme amacı güdüyse, bu "senkronize" özelliğini kaldırmak kesinlikle güvenli değildir. Senkronize

+0

Ancak (yanlıs olmadıkça) sadece uzun ve çifte modifikasyonlar uçucu olmalı, değil mi? – JVerstry

+5

Hayır, yalnızca bu programı tek çekirdekli bir işlemci üzerinde çalıştırmayacaksanız. Atomik yazılar ve okurlarla ilgili değil. Bu, CPU önbellekleri ve ana bellek arasında ileri geri aktarılan değerlerle ilgilidir. Birden fazla iş parçacığı çalıştıran ve "eşitlenmemiş" olan çok çekirdekli bir makinede, farklı iş parçacıkları aynı değişken için farklı değerler görebiliyordu ve çünkü her bir çekirdek önbelleğinde diğerlerinden ve ana bellekten farklı bir değere sahip olacaktır. –

7

(biri için başka bir iş parçacığı tarafından görülebilir değiştirilmiş verileri sağlama) bir kilit alma yanında başka iplik güvenlik etkileri vardır

sürece bu yan etkiler JIT o

istediğini yapma içermez geçerlidir olarak

örnekte bu kilit bu kesinlikle mümkün değildir etkili kilit

+1

İlk cümle burada önemli bir parçasıdır. Senkronize, nesnenin ** herhangi bir ** yönteminin herhangi bir müteakip çağrısına karşı gerçekleşen bir ilişkiyi sağlar. Bu nedenle senkronize edilmiş değişiklikleri kaldırmak, buradaki davranışı. – Voo

+0

Gitme noktası. Mantıklı. – JVerstry

5

VM'nin bir kilidi kaldırabileceği durumlar vardır. Örneğin

Kaçış analizi için

int bar() 
    Foo foo = new Foo(); 
    return foo.getWhatever(); 

VM o foo ikna edebilirim başka iş parçacığı tarafından görülemez, başka nedenle kimse kilitlemek için çalışacağız, getWhatever yöntemin therfore kilitleme bırakılabilir.

Kilit irileşmesi

Foo foo = ...; 
void bar() 
    a(); 
    foo.getWhatever(); 
    b(); 
    foo.getWhatever(); 
    c(); 

yasal olarak bir kilitleme eylemi

void bar() 
    synchronized(foo) 
     a(); 
     foo.getWhatever_without_lock(); 
     b(); 
     foo.getWhatever_without_lock(); 
     c(); 

başka iyi haber kilitli bölge nedeniyle adaptif kilitleme, bu yüzden kısa olması nedeniyle ise, VM en olası irade kurtarmak için birleşti edebilirsiniz Bunun için spin kilit kullanın; Başarısız kilitleme nedeniyle iplik süspansiyonu çok düşüktür.

+0

Bunun için bir referans verebilir misiniz? –

+0

@Ryan – irreputable

+0

terimlerini kullanın Ayrıca bkz. Http://stackoverflow.com/questions/18996783/what-is-the-synchronization-cost-of-calling-a-synchronized-method-from-a-synchro – Raedwald

İlgili konular