2014-04-20 22 views
5

Eşzamanlılık sorunları hakkında birkaç yazı okuyorum ama hala bir şey hakkında emin değilim. Senkronize edildiğinde, bir uçbirimde kilit açılacağı zaman, sonraki iş parçacığının her zaman değiştirilen nesneyi okuduğundan, ücretsiz olarak uçucu işlevler aldığımı söyleyebilirim. Uçucu ile, bir nesnenin değeri hemen diğer konulara yansıtılır. Ama senkronize kullandığımda, nesne üzerindeki kilit nedeniyle onu hemen yansıtabilme olasılığı yoktur. Kilit serbest bırakıldığında, sadece başka bir iş parçacığı ona erişebilir. Yani değeri hemen diğer konulara yansıtmayı umursamıyorum. Bu hakkımı anlıyor muyum? her zaman 1 2 3 4 5 6 7 8 9 uçucu olmayanJava Senkronizasyon kullanıldığında, ücretsiz olarak volatil işlevlerim var mı?

[UPDATE]
Örnek yazdırılır.

package main; 

public class Counter 
{ 
    public static long count = 0; 
} 

public class UseCounter implements Runnable 
{ 
    public void increment() 
    { 
     synchronized (this) 
     {  
      Counter.count++; 
      System.out.print(Counter.count + " "); 
     } 
    } 

    @Override 
    public void run() 
    { 
     increment(); 
     increment(); 
     increment(); 
    } 
} 

public class DataRace 
{ 
    public static void main(String args[]) 
    { 
     UseCounter c = new UseCounter(); 

     Thread t1 = new Thread(c); 
     Thread t2 = new Thread(c); 
     Thread t3 = new Thread(c); 

     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 
+0

Güncelleştirmeniz hakkında: Şu anda ne yazıyor? bir şey ifade eder. Veri yarış koşulları genellikle en azından onları beklediğinizde gizlenir ve çoğaltılması ve çözülmesi çok zordur. Önemli olan, Java Bellek Modelinin kurallarını takip ettiyseniz. –

+0

Ok teşekkürler. Her ne kadar uçsuz bucaksız davranışlar üretemesem de (kodu 1000.000 kez bir döngüde çalıştırdığımda bile değil) aklımda tutacağım. – Bevor

cevap

2

Hayır, uçucu bir erişim Java Hafıza Modeli (belirli uygulamalarla ilgili rağmen, olabilir, ama o bağımlı olmamalıdır)

Java Language Specification 17.4.4 (on the Java Memory Model):

göre senkronize erişim ima edilmez Senkronizasyon işlemler senkronize-şu şekilde tanımlanır: eylemleri ile ilgili aşağıdaki oluşturur:

  • monitör m senkronize üzerine bir açma eylemi Sonraki tüm kilit eylemleri ile m (burada "sonraki" senkronizasyon sırasına göre tanımlanmıştır).

  • uçucu bir değişken v (§8.3.1.4) senkronize-ile takip eden her için bir yazma (senkronizasyon düzenine göre tanımlanan "sonraki") herhangi bir parçacığı tarafından v okur.

volatile bir değişken çalışır ve synchronized bir nesnenin monitör ('bağlayıcı') üzerinde çalışır. Bir Konu, aynen (örneğin alanı) V nesne O sadece bir uçucu madde değişken okuma nesne O ve başka bir iplik B senkronize bir blok çıkıldığı

, daha sonra yine değildir orada iki iplik arasında senkronize-bağlantılı bir ilişki. İş parçacığı, B iş parçacığı O nesnesinde veya iş parçacığı O nesnesinde V volatil alanı erişilene kadar iş parçacığı tarafından B iş parçacığı veya tersi tarafından yapılan herhangi bir veri değişikliği göreceğinin garantisi yoktur.

+0

Tamam, bu, dışsal değişkenlere birkaç iş parçacığıyla erişirken her zaman uçucu kullanmam gerektiği anlamına mı geliyor? Güncellenmiş sorularıma bak. Her zaman 1 2 3 4 5 6 7 8 9'u uçucu olmadan yazdırır. Yani bunun garanti edilmediği anlamına mı geliyor? – Bevor

+0

Bir iplik (B) başka bir iplik (A) bunu yaptıktan sonra bir uçucu alan okursa (veya yazar), o zaman B ipliği uçucu olmayanlar da dahil olmak üzere herhangi bir değişkene (aynı uçucu alana erişmeden önce) A iplikini işleyen * tüm * modifikasyonları görecektir. olanlar. Aynı uçucu değişkenlere erişmek, bunu yapan iplikler arasında bir "gerçekleşen-öncesi" ilişki yaratır. –

1

Geçici bir değişkene sahip olmak senkronize erişim ile aynı değildir. Bir değişkeni uçucu olarak işaretlediğinizde, nesneye erişen Thread nesnesi yerel bir önbellek tutmayacak ve sadece bir "kopya" olacaktır. Eğer ikisini (senkronize ve uçucu) birleştirirseniz, o zaman her zaman güncellenmiş versiyon olacaktır ve bununla çakışan bir erişiminiz olmayacaktır.

+0

Teşekkürler, ancak neden çakışan bir erişim olduğunu anlamıyorum, çünkü bir nesneyi senkronize ile kilitlediğimde ve kilitlediğimde, ilk iş parçacığının yerel bir kopyası yapıp yapmadığını umursamıyorum? Nesne kilidi açıldığında, sonraki iş parçacığının değiştirilmiş nesneye erişim kazanacağı garanti edilmez mi? – Bevor

+0

“Uçucu” nun ardındaki fikir, daima değişkenin en güncel versiyonunu alacağınızdır. Bir iş parçacığı önbelleği tuttuğunda, yeni değerler almak için zaman kazanmak amacıyla bunu yapar ancak değişken değişkenler önbelleğe alınmaz – Rogue

0

Kodunuz 1 2 3 4 5 6 7 8 9 yazdιrιlabilir.nedeni bir dizi varsa Konu t1 Counter.count yazar böyle

  1. olarak olmasıdır
  2. Konu t1 nesne c'yi kilidini
  3. Konu t2 kilitler c
  4. Konu t2 Counter.count
  5. okur nesne sonra

o adım 4'te okuma aşamasında yazma gördüğü 1.

Buile aynı değildir garantilidirYazımın belleğe hemen yansıtılması garanti edilmediğinden, yalnızca adım 1'deki yazmanın 3. adımın sonunda t2'ye görünür olması garanti edilir.

İlgili konular