'Senkronize' ne anlama geliyor?


993

synchronizedAnahtar kelimenin kullanımı ve önemi ile ilgili bazı sorularım var .

  • synchronizedAnahtar kelimenin önemi nedir ?
  • Yöntemler ne zaman olmalı synchronized?
  • Programlı ve mantıksal olarak ne anlama geliyor?


1
hashmap ve hashtable ve senkronizasyon arasında faydalı tartışma: stackoverflow.com/questions/40471/java-hashmap-vs-hashtable
limc


1
İlk yorumdan tüm dokümantasyon bağlantısını geçtim ve son paragrafa gelene kadar anlamadım. Bağlantıları yapıştırmak ve hiçbir şeyden alıntı yapmak yerine, bağlantıları yapıştırmak ve bir teklif eklemek daha yararlı olabilir.
Rakib

Yanıtlar:


878

synchronizedAnahtar kelime okuma ve aynı değişkenler, nesneler ve kaynaklara yazma farklı konuları ile ilgili. Bu Java'da önemsiz bir konu değil, ancak Sun'ın bir alıntısı:

synchronized yöntemler, iş parçacığı etkileşimini ve bellek tutarlılığı hatalarını önlemek için basit bir strateji sağlar: bir nesne birden fazla iş parçacığında görünürse, o nesnenin değişkenlerine tüm okuma veya yazma işlemleri senkronize yöntemlerle yapılır.

Çok, çok küçük bir özetle: Aynı 'kaynağa' okuma ve yazma yapan iki iş parçanız varsa, adlı bir değişken söyleyin foo, bu iş parçacıklarının değişkene atomik bir şekilde erişmesini sağlamanız gerekir. synchronizedAnahtar kelime olmadan, iş parçanız 1, yapılan iş parçacığı 2'yi değiştiremez fooveya daha da kötüsü, yalnızca yarısı değiştirilebilir. Mantıksal olarak beklediğiniz bu olmaz.

Yine, bu Java'da önemsiz olmayan bir konudur. Daha fazla bilgi edinmek için burada SO ve Interwebs ile ilgili konuları inceleyin:

"Brian Goetz" adı beyninizdeki "eşzamanlılık" terimi ile kalıcı olarak ilişkilendirilene kadar bu konuları araştırmaya devam edin .


71
Temel olarak, bu Senkronize anahtar kelime yöntemlerinizi evre güvenli kılar?
Rigo Vides

82
Senkronize edilen anahtar kelime, kod dizinizi güvenli hale getiren araçlardan biridir. Sadece kendi başına bir yöntem veya değişken üzerinde senkronize edilmiş kullanmak hile yapabilir veya etmeyebilir. Java Bellek Modeli hakkında temel bir anlayışa sahip olmak, eşzamanlılığın doğru olması için gerçekten önemlidir.
Stu Thompson

28
Brian Goetz (veya belki Jon Skeet) olmadığınız sürece, Java eşzamanlılığını sadece dil ilkelleriyle (senkronize, uçucu) doğru yapmak neredeyse imkansızdır. Yeni başlayanlar için java.util.concurrent paketini kullanın ve bunun üzerine inşa edin.
Thilo

12
Daha açık bir şekilde: senkronize yöntemler aynı anda birden çok iş parçacığından çağrılamaz.
peterh - Monica

2
@peterh senkronize bundan daha fazlasını yapar, bu nedenle daha ayrıntılı bir açıklama
Stu Thompson

293

Sanırım yeterince teorik açıklama yaptık, bu yüzden bu kodu düşünün

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Not: synchronizedönceki iş parçacığının yürütülmesi bitmediği sürece bir sonraki iş parçacığının yöntem testine () çağrısını engeller. Konular bu yönteme birer birer erişebilir. olmadansynchronizedTüm aynı anda bu yönteme erişebilirsiniz.

Bir iş parçacığı, nesnenin eşitlenmiş 'test' yöntemini çağırdığında (burada nesne, 'TheDemo' sınıfının bir örneğidir), bu nesnenin kilidini alır, herhangi bir yeni iş parçacığı, önceki iş parçacığı kadar aynı nesnenin HERHANGİ bir eşitlenmiş yöntemini çağıramaz kilidi almış olan kilidi serbest bırakmaz.

Sınıfın herhangi bir statik senkronize yöntemi çağrıldığında da benzer bir şey olur. İş parçacığı sınıfla ilişkili kilidi alır (bu durumda o sınıfın bir örneğinin statik olmayan eşitlenmiş yöntemi herhangi bir iş parçacığı tarafından çağrılabilir, çünkü bu nesne düzeyi kilidi hala kullanılabilir). Sınıf düzeyi kilidi, şu anda kilidi tutan iş parçacığı tarafından serbest bırakılmadığı sürece, başka hiçbir iş parçacığı, sınıfın statik senkronize yöntemini çağıramaz.

Senkronize edilmiş çıkış

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Senkronize olmayan çıkış

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9

7
Büyük örnek, teoriyi bilmek iyidir, ancak kod her zaman daha spesifik ve eksiksizdir.
Santi Iglesias

2
@SantiIglesias "Tamamlandı" mı? Hayır! Bu örnek, kilitleme davranışını gösterir synchronized, ancak bellek tutarlılığı yok sayılır.
Stu Thompson

2
@Stu Thompson bellek tutarlılığı kilitlemenin sonucudur
Dheeraj Sachan

@DheerajSachan Bu mantıkla bir ReentrantLock kullanmak bellek tutarlılığına neden olur. Öyle değil.
Stu Thompson

3
@boltup_im_coding: start () yöntemi, Thread'ı "RUNNABLE" durumuna getirir, yani yürütmeye veya zaten çalıştırılmaya hazırdır. Runnable durumundaki başka bir iş parçacığının (genellikle daha yüksek önceliğe sahip olması gerekmez) sıraya atlaması ve yürütmeye başlaması olabilir. Yukarıdaki örnekte, THREAD 3, THREAD 2'den önce CPU aldı.
Sahil J

116

synchronizedAnahtar birden fazla ilmek kodu veya nesnenin bir blok eş zamanlı erişimi engeller. Tüm yöntemleri Hashtablevardır synchronized, bu nedenle aynı anda yalnızca bir iş parçacığı yürütebilir.

synchronizedGibi kurguları kullanırken HashMap, tutarlılık hatalarını önlemek için kodunuzda iş parçacığı güvenliği özellikleri oluşturmanız gerekir.


81

synchronizedçok iş parçacıklı bir ortamda, synchronizedyöntem (ler) / blok (lar) a sahip bir nesnenin iki iş parçacığınınsynchronized kod yöntemlerine / kod bloklarına aynı anda . Bu, bir iş parçacığı başka bir iş parçacığı güncelleştirirken okuyamayacağı anlamına gelir.

Bunun yerine ikinci iş parçacığı, ilk iş parçacığı yürütme işlemini tamamlayana kadar bekler. Genel gider hızdır, ancak avantaj verilerin tutarlılığı garanti edilir.

Uygulamanız tek iş parçacıklıysa, synchronizedbloklar fayda sağlamaz.


54

synchronizedAnahtar kelime yöntemi girerken (statik bir yöntem olmadığı sürece verilen nesne örneğin) tek iplik aynı anda yöntemi yürütebileceği böylece, bir kilit elde etmek için bir iş parçacığı neden olur.

Bu sık sık sınıf iş parçacığı güvenli yapma denir, ama bunun bir örtmece olduğunu söyleyebilirim. Senkronizasyonun Vector öğesinin dahili durumunu bozulmaya karşı koruduğu doğru olsa da, bu genellikle Vector kullanıcısına çok fazla yardımcı olmaz.

Bunu düşün:

 if (vector.isEmpty()){
     vector.add(data);
 }

İlgili yöntemler senkronize olsa da, ayrı ayrı kilitlendikleri ve kilidinin açıldığı için maalesef iki zamanlanmış iş parçacığı iki öğeli bir vektör oluşturabilir.

Dolayısıyla, uygulama kodunuzda da senkronize etmeniz gerekir.

Yöntem düzeyinde senkronizasyon a) ihtiyacınız olmadığında pahalı olduğu ve b) senkronizasyon gerektiğinde yetersiz olduğu için, artık senkronize edilmemiş değiştirmeler (Vector durumunda ArrayList) vardır.

Daha yakın zamanlarda, çoklu iş parçacığı sorunlarıyla ilgilenen bir dizi akıllı yardımcı programla eşzamanlılık paketi yayınlandı.


26

genel bakış

Java'da senkronize edilen anahtar kelime, iş parçacığı güvenliği ile ilgilidir, yani birden fazla iş parçacığı aynı değişkeni okuduğunda veya yazdığında.
Bu doğrudan (aynı değişkene erişerek) veya dolaylı olarak (aynı değişkene erişen başka bir sınıf kullanan bir sınıf kullanarak) olabilir.

Senkronize anahtar kelime, birden çok iş parçacığının aynı değişkene güvenli bir şekilde erişebileceği bir kod bloğu tanımlamak için kullanılır.

Daha derine

Sözdizimi açısından, synchronizedanahtar kelime Objectparametresi olarak ( kilit nesnesi olarak adlandırılır ) alır ve ardından a gelir { block of code }.

  • Yürütme bu anahtar sözcükle karşılaştığında, geçerli iş parçacığı kilit nesnesini "kilitlemeye / almaya / sahiplenmeye" (seçiminizi yapmaya) ve kilit alındıktan sonra ilişkili kod bloğunu yürütmeye çalışır.

  • Senkronize kod bloğundaki değişkenlere yapılan tüm yazma işlemlerinin, aynı kilit nesnesini kullanarak senkronize bir kod bloğu içinde benzer şekilde kod yürüten diğer tüm iş parçacıkları tarafından görüleceği garanti edilir .

  • Bir seferde yalnızca bir iş parçacığı kilidi tutabilir, bu sırada aynı kilit nesnesini almaya çalışan diğer tüm iş parçacıkları bekler (yürütülmelerini duraklatır). Yürütme senkronize kod bloğundan çıktığında kilit serbest bırakılır.

Senkronize yöntemler:

synchronizedBir yöntem tanımına anahtar kelime eklemek , kilit nesnesi this (örneğin yöntemler) ve ClassInQuestion.getClass() (sınıf yöntemleri için ) olmak üzere senkronize edilmiş bir kod bloğuna sarılmış olan tüm yöntem gövdesine eşittir .

- Örnek yöntemi, staticanahtar kelimesi olmayan bir yöntemdir .
- Sınıf yöntemi staticanahtar kelimeye sahip bir yöntemdir .

Teknik

Senkronizasyon olmadan, okumaların ve yazmaların hangi sırayla gerçekleşeceği garanti edilmez ve büyük olasılıkla değişkeni çöple birlikte bırakır.
(Örneğin, bir değişken, bir iş parçacığı tarafından yazılan bitlerin yarısı ve başka bir iş parçacığı tarafından yazılan bitlerin yarısı ile değişebilir ve değişkeni, iş parçacıklarının hiçbirinin yazmaya çalışmadığı, ancak her ikisinin birleşik karmaşası şeklinde bırakabilir.)

Başka bir iş parçacığı okumadan önce bir iş parçacığında bir yazma işlemini tamamlamak yeterli değildir, çünkü donanım değişkenin değerini önbelleğe almış olabilir ve okuma iş parçacığı, yazılanlar yerine önbelleğe alınmış değeri görür o.

Sonuç

Bu nedenle Java'nın durumunda, iş parçacığı hatalarının oluşmamasını sağlamak için Java Bellek Modelini izlemeniz gerekir.
Başka bir deyişle: Senkronizasyon, atom işlemleri veya bunları sizin için davlumbazların altında kullanan sınıfları kullanın.

Kaynaklar

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java® Dil Özellikleri, 2015-02-13


Üzgünüm, ama bu örnek var ve anlamını anlamıyorum: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); senkronize (i1) {Tamsayı i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. 1. Bloğu neden ilk kez çağırdınız ve bu çağrının kod üzerinde bir etkisi yok? 2. İkinci örnek, birincide bloğun çağrılmasına rağmen iş parçacığı için güvenli olacak mı?
Adryr83

1
@ Adryr83 Bir sorunuz varsa, muhtemelen yeni bir soru göndererek bunu sorabilirsiniz. Ama burada olduğumuz için elimden gelenleri ayrıştıracağım (sorunuzun anlaşılması biraz zor). Bu kod parçası hakkında söyleyebileceğimden, senkronizasyon gerektiren bir şey içermiyor gibi görünüyor. Bağlam dışında. Öneri: Yapabiliyorsanız, kodu daha küçük münferit parçalara bölmeye çalışın ve ardından bunlarla ilgili yanıtları arayın. Küçük ve izole problemleri anlamaya çalışmak, büyük bir kod bloğunu bulmaya çalışmaktan daha kolaydır.
Gima

21

Bir futbol sahasında bulabileceğiniz gibi bir tür turnike olarak düşünün. İçeri girmek isteyen insanların paralel buharları var ama turnikede 'senkronize' oluyorlar. Bir seferde yalnızca bir kişi geçebilir. Üstesinden gelmek isteyen herkes yapacak, ama geçene kadar beklemek zorunda kalabilirler.


16

Senkronize edilen anahtar kelime nedir?

İş parçacıkları öncelikle alanlara ve başvuru alanlarının başvurduğu nesnelere erişimi paylaşarak iletişim kurar. Bu iletişim şekli son derece etkilidir, ancak iki tür hatayı mümkün kılar: iş parçacığı etkileşimi ve bellek tutarlılığı hataları . Bu hataları önlemek için gereken araç senkronizasyondur.

Senkronize bloklar veya yöntemler, iplik girişimini önler ve verilerin tutarlı olduğundan emin olun. Herhangi bir zamanda, sadece bir iş parçacığı bir kilit alarak senkronize bir bloğa veya yönteme ( kritik bölüm ) erişebilir . Diğer diş (ler) kritik bölüme erişmek için kilidin serbest bırakılmasını bekleyecektir .

Yöntemler ne zaman senkronize edilir?

Yöntem synchronizedtanımına veya bildirimine eklediğinizde yöntemler senkronize edilir. Ayrıca belirli bir kod bloğunu bir yöntemle senkronize edebilirsiniz.

Profesyonel dilbilgisi ve mantıksal olarak ne anlama geliyor?

Bu, bir kilit alarak sadece bir iş parçacığının kritik bölüme erişebileceği anlamına gelir . Bu iş parçacığı bu kilidi serbest bırakmadıkça, diğer tüm iş parçacığı kilit almak için beklemek zorunda kalacak. Kritik bölüme girme erişimi yokKilit edinmeden .

Bu bir sihirle yapılamaz. Kritik bölüm (ler) tanımlamak programcının sorumluluğundadır ve buna göre korumak . Java, uygulamanızı korumak için bir çerçeve sağlar, ancak korunacak tüm bölümlerin nerede ve ne olacağı programcının sorumluluğundadır.

Java dokümantasyon sayfasından daha fazla detay

İçsel Kilitler ve Senkronizasyon:

Senkronizasyon, kendinden kilitli veya monitör kilidi olarak bilinen bir dahili varlık etrafında oluşturulur. İçsel kilitler senkronizasyonun her iki yönünde de rol oynar: bir nesnenin durumuna özel erişimin sağlanması ve görünürlük için gerekli olan ilişkiden önce ilişkiler kurulması.

Her nesnenin kendisiyle ilişkilendirilmiş kendinden kilit vardır . Kural olarak, bir nesnenin alanlarına özel ve tutarlı erişime ihtiyaç duyan bir iş parçacığının, nesneye erişmeden önce kendinden kilit alması ve onlarla iş bitince iç kilidi serbest bırakması gerekir.

Bir ipliğin, kilidi edindiği ve kilidi serbest bıraktığı zaman arasında içsel kilide sahip olduğu söylenir. Bir iş parçacığının kendinden kilitlemesine sahip olduğu sürece, başka hiçbir iş parçacığı aynı kilidi alamaz. Diğer iş parçacığı, kilidi almaya çalıştığında engellenir.

Bir iş parçacığı içsel bir kilidi serbest bıraktığında, o eylem ile aynı kilidin daha sonraki herhangi bir edinimi arasında önceden gerçekleşen bir ilişki kurulur.

Yöntemleri senkronize etmenin iki etkisi vardır :

İlk olarak, aynı nesne üzerinde senkronize yöntemlerin iki çağrılması için serpiştirmek mümkün değildir.

Bir iş parçacığı, bir nesne için eşitlenmiş bir yöntem yürütürken, aynı iş parçacığı için eşitlenmiş yöntemleri çağıran diğer tüm iş parçacıkları, ilk iş parçacığı nesne ile yapılana kadar.

İkincisi, senkronize edilmiş bir yöntemden çıkıldığında, otomatik olarak aynı nesne için senkronize edilmiş bir yöntemin herhangi bir çağrılmasıyla önce gerçekleşen bir ilişki kurar.

Bu, nesnenin durumundaki değişikliklerin tüm iş parçacıkları tarafından görülebilir olmasını sağlar.

Senkronizasyon için diğer alternatifleri arayın:

Java ile senkronize (bu) kaçının?


11

Synchronized normal methodeşdeğeri Synchronized statement(bunu kullanın)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static methodeşdeğeri Synchronized statement(sınıfı kullan)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Senkronize ifade (değişken kullanılarak)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

İçin synchronized, biz de var Synchronized Methodsve Synchronized Statements. Ancak, Synchronized Methodsbuna benzer, Synchronized Statementsbu yüzden sadece anlamamız gerekiyor Synchronized Statements.

=> Temel olarak, sahip olacağız

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

İşte anlamaya yardımcı olan 2 düşünce synchronized

  • Her nesnenin / sınıfın intrinsic lockkendisiyle bir ilişkisi vardır.
  • Bir iş parçacığı a'yı çağırdığında synchronized statement, o nesne intrinsic lockiçin otomatik olarak alınır synchronized statement'sve yöntem döndüğünde onu serbest bırakır. Bir iş parçacığı bir sahip olduğu sürece intrinsic lock, başka bir iş parçacığı aynı kilit => iş parçacığı güvenli elde edemez .

=> Bir thread Ainvokes synchronized(this){// code 1}=> sahip olduğu tüm blok kodu (sınıf içi) synchronized(this)ve hepsi aynı synchronized normal method(sınıf içi) kilitlidir çünkü aynı kilit. thread AKilidi açtıktan sonra yürütülür ("// kod 1" bitti).

Bu davranış synchronized(a variable){// code 1}veya biçimine benzer synchronized(class).

AYNI KİLİT => kilit (hangi yönteme veya hangi ifadelere bağlı değil?)

Senkronize yöntem veya senkronize ifadeler mi kullanıyorsunuz?

synchronized statementsDaha uzatılabilir olduğu için tercih ederim . Örneğin, gelecekte, yöntemin yalnızca bir kısmını senkronize etmeniz gerekir. Örnek olarak, 2 senkronize yönteminiz vardır ve birbiriyle ilişkili değildir , ancak bir iş parçacığı bir yöntemi çalıştırdığında, diğer yöntemi engeller (kullanım tarafından önlenebilir synchronized(a variable)).

Ancak, senkronize yöntem uygulamak basit ve kod basit görünüyor. Bazı sınıflar için, yalnızca 1 senkronize yöntem veya sınıftaki birbiriyle ilişkili tüm senkronize yöntemler => synchronized methodkodu daha kısa ve anlaşılması kolay hale getirmek için kullanabiliriz

Not

(çok fazla ilgisi yoktur synchronized, nesne ve sınıf arasındaki fark veya hiç statik olmayan ve statik).

  • Kullantığınızda synchronizedveya normal yöntem veya synchronized(this)veya synchronized(non-static variable)her nesne örneği temel eşitlenir.
  • Kullandığınızda synchronizedveya statik yöntemi veya synchronized(class)veya synchronized(static variable)bunun sınıfına tabanını senkronize olacak

Referans

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Umarım yardımcı olur


11

İşte Java Dersleri'nden bir açıklama .

Aşağıdaki kodu göz önünde bulundurun:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

eğer countbir örneğidir SynchronizedCounter, daha sonra senkronize bu yöntemleri yapma iki etkiye sahiptir:

  • İlk olarak, aynı nesne üzerinde senkronize yöntemlerin iki çağrılması için serpiştirmek mümkün değildir. Bir iş parçacığı, bir nesne için eşitlenmiş bir yöntem yürütürken, aynı iş parçacığı için eşitlenmiş yöntemleri çağıran diğer tüm iş parçacıkları, ilk iş parçacığı nesne ile yapılana kadar.
  • İkincisi, senkronize edilmiş bir yöntemden çıkıldığında, otomatik olarak aynı nesne için senkronize edilmiş bir yöntemin herhangi bir çağrılmasıyla önce gerçekleşen bir ilişki kurar. Bu, nesnenin durumundaki değişikliklerin tüm iş parçacıkları tarafından görülebilir olmasını sağlar.

9

Eşitlendiğimi anlamak için, derleyicinin yönteminizin etrafına bir monitor.enter ve monitor.exit yazdığı anlamına gelir. Bu nedenle, nasıl kullanıldığına bağlı olarak iş parçacığı güvenli olabilir (yani, sınıfınızın ne yaptığına bağlı olarak threadsafe olmayan senkronize yöntemlerle bir nesne yazabilirsiniz).


5

Diğer cevapların eksik olması önemli bir husustur: bellek engelleri . İş parçacığı senkronizasyonu temel olarak iki bölümden : serileştirme ve görünürlük. Önemsiz ve son derece önemli bir konu olduğu için (birden çok iş parçacığı tarafından erişilen paylaşılan verileri değiştirirseniz) herkese Google'a "jvm bellek bariyeri" için tavsiyede bulunuyorum. Bunu yaptıktan sonra, açık senkronizasyonu kullanmaktan kaçınmaya yardımcı olan java.util.concurrent paketinin sınıflarına bakmanızı öneririm, bu da programları basit ve verimli tutmaya yardımcı olur, hatta belki de kilitlenmeleri önler.

Böyle bir örnek ConcurrentLinkedDeque'dir . Komut deseni ile birlikte , komutları eşzamanlı kuyruğa doldurarak son derece verimli çalışan iş parçacıkları oluşturmaya izin verir - açık senkronizasyon gerekmez, kilitlenme mümkün değildir, açık uyku () gerekmez, sadece take () diyerek kuyruğu yoklayın.

Kısacası: "bellek senkronizasyonu" bir iş parçacığı başlattığınızda, iş parçacığı sona erdiğinde, geçici bir değişkeni okuduğunuzda, bir monitörün kilidini açtığınızda (senkronize bir blok / işlev bıraktığınızda) dolaylı olarak gerçekleşir . Bu "senkronizasyon" etkiler (bir anlamda "yıkar ") tüm yazılar bu işlemden önce yapılır. Yukarıda belirtilen ConcurrentLinkedDeque durumunda , dokümantasyon "diyor":

Bellek tutarlılığı efektleri: Diğer eşzamanlı koleksiyonlarda olduğu gibi, bir nesneyi bir ConcurrentLinkedDeque içine yerleştirmeden önce bir iş parçacığındaki eylemler, o öğenin başka bir iş parçacığında ConcurrentLinkedDeque öğesine erişilmesi veya bu öğenin kaldırılmasından sonraki eylemlerden önce gerçekleşir.

Bu örtük davranış biraz zararlı bir durumdur, çünkü fazla tecrübesi olmayan çoğu Java programcısı, bu nedenle verilen çok şey alacaktır. Ve sonra Java, farklı bir iş yükünün olduğu üretimde yapılması gerekeni yapmazsa ve aynı zamanda eşzamanlılık sorunlarını test etmek oldukça zorlaştıktan sonra aniden bu iş parçacığına rastlarsınız.


3

Senkronizasyon, tek bir nesne ile ilişkilendirilirse birden çok iş parçacığının, belirli bir nesne üzerinde senkronize blok kullanıldığında kirli okuma ve yazmayı engelleyebileceği anlamına gelir. Size daha fazla açıklık sağlamak için bir örnek verelim:

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

İki MyRunnable sınıf nesnesi oluşturduk; runnable1 iş parçacığı 1 ve iş parçacığı 3 & runnable2 yalnızca iş parçacığı 2 ile paylaşılıyor. Şimdi t1 ve t3 senkronize kullanılmadan başladığında, hem diş 1 hem de 3'ün aynı anda diş 2 için var değerini etkilediğini öneren PFB çıktısı, var'ın kendi belleğine sahip olduğunu gösterir.

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

Eşzamanlı olarak, iş parçacığı 1'in tüm senaryolarda tamamlanmasını bekleyen iş parçacığı 3. Biri iş parçacığı 1 ve iş parçacığı 3 tarafından paylaşılan runnable1 üzerinde ve diğeri yalnızca iş parçacığı 2 tarafından paylaşılan runnable2 üzerinde iki kilit edinilmiş.

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18

Senkronize edilmiş bundan daha da fazlası anlamına gelir: bellek bariyeri üzerinde derin bir etkisi vardır.
user1050755

1

senkronize basit, hiçbir iş parçacığının bloğa / yönteme aynı anda erişemeyeceği anlamına gelir. Bir sınıfın herhangi bir bloğunun / yönteminin senkronize edildiğini söylediğimizde, aynı anda yalnızca bir iş parçacığına erişilebileceği anlamına gelir. Dahili olarak ona erişmeye çalışan iş parçacığı önce o nesne üzerinde bir kilit alır ve bu kilit mevcut olmadığı sürece, başka hiçbir iş parçacığı sınıfın o örneğinin senkronize yöntemlerinden / bloklarından hiçbirine erişemez.

Başka bir iş parçacığının, eşitlenecek şekilde tanımlanmamış aynı nesnenin bir yöntemine erişebileceğini unutmayın. Bir iş parçacığı arayarak kilidi açabilir

Object.wait()

0

synchronizedJava'daki blok çoklu kullanımda bir monitördür. synchronizedaynı nesne / sınıf ile blok sadece tek bir iş parçacığı tarafından yürütülebilir, diğerleri bekliyor. race conditionBirkaç iş parçacığı aynı değişkeni güncellemeye çalıştığında duruma yardımcı olabilir (ilk adım volatileHakkında'yı kullanmaktır )

Java 5synchronizeddestekleyerek genişletildi happens-before[Hakkında]

Bir monitörün kilidinin açılması (senkronize blok veya yöntem çıkışı) - aynı monitörün her sonraki kilidinden (senkronize blok veya yöntem girişi) önce gerçekleşir.

Bir sonraki adım java.util.concurrent

uçucu vs senkronize


-6

senkronize Java, bellek tutarsızlığı ve iş parçacığı girişim hatası önlemek için çok iş parçacıklı ortamda ilişkiden önce gerçekleşmesi için kullanılan bir anahtar kelimedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.