2012-02-08 32 views
26

senkronize anahtar kelime kullanımı synchronized anahtar kelime ile test ediyordum. Onu çalıştırdığınızda, iki iş parçacığı countMe() yöntemini çağırarak çıktısı bu çıktıyı üretirÖğrenme Java,

public class MyTest { 
    static int i = 0; 
    public static void main(String[] args) { 
     new Thread(t1).start(); 
     new Thread(t2).start(); 
    } 

    private static void countMe(String name){ 
     i++; 
     System.out.println("Current Counter is: " + i + ", updated by: " + name); 
    } 

    private static Runnable t1 = new Runnable() { 
     public void run() { 
      try{ 
       for(int i=0; i<5; i++){ 
        countMe("t1"); 
       } 
      } catch (Exception e){} 

     } 
    }; 

    private static Runnable t2 = new Runnable() { 
     public void run() { 
      try{ 
       for(int i=0; i<5; i++){ 
        countMe("t2"); 
       } 
      } catch (Exception e){} 
     } 
    }; 
} 

:

Current Counter is: 1 
Current Counter is: 2 
Current Counter is: 4 
Current Counter is: 5 
Current Counter is: 6 
Current Counter is: 7 
Current Counter is: 3 
Current Counter is: 8 
Current Counter is: 9 
Current Counter is: 10 

Ve ben yöntemini countMe() değiştirdiğinizde:

İşte denedim bir örnek

Current Counter is: 1 
Current Counter is: 2 
Current Counter is: 3 
Current Counter is: 4 
Current Counter is: 5 
Current Counter is: 6 
Current Counter is: 7 
Current Counter is: 8 
Current Counter is: 9 
Current Counter is: 10 
01:
private synchronized static void countMe(){ 
     i++; 
     System.out.println("Current Counter is: " + i); 
} 

Bu çıktıyı almak

Bu bana synchronized'un amacını net bir şekilde anlatabilmesine rağmen, synchronized'u kullanabileceğimiz başka bir neden olduğunu da bilmek istiyorum. Ya da burada yaptığım şey, bu synchronized anahtar kelimesinin kullanılmasına neden ihtiyaç duyduğumuz tek mi?

Teşekkürler.

DÜZENLEME: Birlikte karıştı başka şey sayaç Bana biraz imkansız görünüyor, ancak benzer sonuçlar denemek her zaman olur do 7 sonra 3'e gitti neden ilk çıktıda, bu normaldir olmasıdır ?

+0

Bu parçaların değiştiği konusunda garanti verilmez. 3 sayılan iş parçacığı, diğer iş parçacığı 7'ye kadar sayım yapana kadar yazdırılamayabilir. –

+0

teşekkürler, ancak sonraki 7 yazdırma baskısı nasıl olur? 3. Yani 6 veya 5 yazabilirim, ancak bu yeni yöntem çağrısı gibi görünüyor 3 sonra ben okumadım, bu çok garip geliyor. Yani her zaman 2 veya daha fazla iş parçacığı aynı kod bloğu kullanmak zorunda zaman senkronize kullanmak akıllıca olmalı? – 911TurboS

+5

İş parçacığının adını yazdırmanızı öneririm ve karışıklığın nerede olduğu konusunda daha açık hale gelir. Eşzamanlılık karmaşık bir konu ve basit cevaplar yok. Tercihim, aktör kalıplarını kullanmak ve mümkün olduğu kadar iş parçacıkları arasında çok az veri paylaşmak. ideal olarak, yok. Kodu çok verimli bir şekilde işleyen bir iş parçacığı genellikle yeterlidir. –

cevap

24

İki şey:

Birincisi, serpiştirmek için aynı nesne üzerinde senkronize yöntemlerden iki çağrımı için mümkün değildir. Bir iş parçacığı, bir nesne için eşitlenmiş bir yöntemi yürütürken, aynı nesne bloğu (yürütmeyi askıya alır) için, eşitlenmemiş yöntemleri ilk nesne işlenene kadar senkronize eden tüm yöntemleri işleyen tüm iş parçacıkları.

İkinci olarak, eşzamanlı bir yöntem çıktığı zaman, aynı nesne için eşzamanlı bir yöntemin daha sonraki herhangi bir çağrısı ile otomatik olarak bir olaydan önce bir ilişki kurar. Bu, nesnenin durumundaki değişikliklerin tüm iş parçacıklarına görülebilir olmasını garanti eder.

Senkronize yöntemler, iş parçacığı girişimi ve bellek tutarlılık hatalarını önlemek için basit bir strateji sağlar: bir nesne birden fazla iş parçacığına görünürse, bu nesnenin değişkenlerine okunan veya yazılan tüm veriler senkronize yöntemlerle yapılır. (Önemli bir istisna: nesne oluşturulduktan sonra değiştirilemeyen son alanlar, nesne oluşturulduktan sonra senkronize olmayan yöntemlerle güvenli bir şekilde okunabilir).

kaynak: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

+0

vulkanino, daha sonra aynı yönteme erişen thread'ları kullanırsam senkronize her zaman kullanmak akıllıca olur. – 911TurboS

+0

+1, benimkilerden daha iyi bir yanıt ... – Nim

+0

@ 911TurboS Bazı yöntemlerde 'synchronized' kullanılarak sadece çok iş parçacıklı kodun doğru şekilde senkronize edilmesi için son derece yetersiz. Veri tutarlılığından (ve muhtemelen diğer birçok şeyden) haberdar olmalısınız. – toto2

11

Vulkanino ana soruya iyi bir cevap verdi, bu yüzden aslında var çünkü sadece 3 sonra 7 yazdırabilirsiniz yaklaşık 3 baskı 7.

sonra sorunuzu ele alacağımız ifadelerinizde Java kodundan çok daha fazla bayt kodu.

Bunun üzerinde genişleyeceğim.

Sen

System.out.println("Current Counter is: " + i); 

diyoruz ve Java kod satırıyla oluşur, ama gerçekten ne olur bir yaratılır dize ve daha sonra bu dize println geçirilir olduğunu. Println yönteminin, aslında satırı konsolda yazmadan önce biraz işlem yapması gerekir.

Kavramsal olarak, aşağıdaki gibi bir şey oluyor.

String printlnString = "Current Counter is: 3" 
--> maybe the other thread executes here 
System.out.println(printlnString); 
--> or maybe the other thread executes here 
i is now equal to 7 and the console has "Current Counter is: 7" 
println writes "Current Counter is: 3" to console 
+0

Sayacın yazılması yerine basit bir diziye yazın, sonra iş parçacığı bittiğinde diziyi yazdırın. – cognacc