Das Schlüsselwort synchronized in Java steuert den Zugriff auf gemeinsame Ressourcen für mehrere Threads. Sie garantiert, dass immer nur ein Thread einen synchronisierten Block oder eine synchronisierte Methode ausführen kann, um Thread-Interferenzen zu verhindern und die Speicherkonsistenz zu gewährleisten.
Verwendung
Das Schlüsselwort synchronized kann auf Methoden oder Blöcke innerhalb von Methoden angewendet werden. Wenn eine Methode oder ein Block als synchronisiert deklariert wird, erhält das angegebene Objekt eine Sperre, und andere Threads werden am Zugriff auf den synchronisierten Code gehindert, bis die Sperre freigegeben wird.
Syntax
Synchronisierte Methode
public synchronized voidsynchronizedMethod(){// method code}Bereitgestellt von
Synchronisierter Block
publicvoidmethod(){synchronized(object){// synchronized code}}Bereitgestellt von
object: Das Objekt, auf das synchronisiert werden soll. Dies ist normalerweise die aktuelle Instanz (this) oder ein bestimmtes Objekt.
Beispiele
Beispiel 1: Synchronisierte Methode
publicclassCounter{private int count =0;public synchronized voidincrement(){
count++;}public int getCount(){return count;}publicstaticvoidmain(String[] args){
Counter counter =newCounter();// Create multiple threads to increment the counter
Thread t1 =newThread(()-> counter.increment());
Thread t2 =newThread(()-> counter.increment());
t1.start();
t2.start();try{
t1.join();
t2.join();}catch(InterruptedException e){
e.printStackTrace();}
System.out.println("Final count: "+ counter.getCount());}}Bereitgestellt von
In diesem Beispiel ist die Methode increment synchronisiert, so dass immer nur ein Thread den Zähler erhöhen kann, was Race Conditions verhindert.
Beispiel 2: Synchronisierter Block
publicclassSynchronizedBlockExample{private final Object lock =newObject();private int count =0;publicvoidincrement(){synchronized(lock){
count++;}}public int getCount(){return count;}publicstaticvoidmain(String[] args){
SynchronizedBlockExample example =newSynchronizedBlockExample();// Create multiple threads to increment the counter
Thread t1 =newThread(()-> example.increment());
Thread t2 =newThread(()-> example.increment());
t1.start();
t2.start();try{
t1.join();
t2.join();}catch(InterruptedException e){
e.printStackTrace();}
System.out.println("Final count: "+ example.getCount());}}Bereitgestellt von
In diesem Beispiel wird ein synchronisierter Block verwendet, um den Zugriff auf die Variable count zu steuern. Das Lock-Objekt stellt sicher, dass jeweils nur ein Thread den synchronisierten Block ausführen kann.
Tipps und bewährte Praktiken
Minimiere synchronisierten Code: Halte synchronisierte Blöcke so kurz wie möglich, um Konflikte zu vermeiden und die Leistung zu verbessern.
Verwende Endgültige Objekte: Wenn du synchronisierte Blöcke verwendest, verwende endgültige Objekte als Sperren, um Konsistenz zu gewährleisten.
Vermeide verschachtelte Synchronisierung: Verschachtelte synchronisierte Blöcke können zu Deadlocks führen. Vermeide sie oder verwende sie mit Vorsicht.
Verwende Concurrent Collections: Für eine komplexe Synchronisierung solltest du nebenläufige Sammlungen aus dem Paket java.util.concurrent verwenden, wie z.B. ConcurrentHashMap, die eine integrierte Synchronisierung bieten.
Flüchtig Schlüsselwort: Für Variablen, auf die mehrere Threads zugreifen, die aber keine komplexe Synchronisierung erfordern, solltest du das Schlüsselwort volatile verwenden, um die Sichtbarkeit sicherzustellen.
Gewindesicherheit: Stelle immer sicher, dass gemeinsam genutzte Ressourcen ordnungsgemäß synchronisiert werden, um die Threadsicherheit zu gewährleisten und Datenbeschädigungen zu vermeiden.
Synchronisierte statische Methoden: Synchronisiere statische Methoden, um einen synchronisierten Zugriff auf Klassenebene zu erzwingen und sicherzustellen, dass nur ein Thread die statische Methode über alle Instanzen hinweg ausführen kann.
publicstatic synchronized voidstaticMethod(){// method code}Bereitgestellt von
Wiedereintritt: Java's intrinsische Sperren sind reentrant, d.h. wenn ein Thread eine Sperre hält, kann er sie wieder erlangen, ohne sich selbst zu blockieren.
Das Schlüsselwort
synchronizedin Java steuert den Zugriff auf gemeinsame Ressourcen für mehrere Threads. Sie garantiert, dass immer nur ein Thread einen synchronisierten Block oder eine synchronisierte Methode ausführen kann, um Thread-Interferenzen zu verhindern und die Speicherkonsistenz zu gewährleisten.Verwendung
Das Schlüsselwort
synchronizedkann auf Methoden oder Blöcke innerhalb von Methoden angewendet werden. Wenn eine Methode oder ein Block als synchronisiert deklariert wird, erhält das angegebene Objekt eine Sperre, und andere Threads werden am Zugriff auf den synchronisierten Code gehindert, bis die Sperre freigegeben wird.Syntax
Synchronisierte Methode
Synchronisierter Block
object: Das Objekt, auf das synchronisiert werden soll. Dies ist normalerweise die aktuelle Instanz (this) oder ein bestimmtes Objekt.Beispiele
Beispiel 1: Synchronisierte Methode
In diesem Beispiel ist die Methode
incrementsynchronisiert, so dass immer nur ein Thread den Zähler erhöhen kann, was Race Conditions verhindert.Beispiel 2: Synchronisierter Block
In diesem Beispiel wird ein synchronisierter Block verwendet, um den Zugriff auf die Variable
countzu steuern. Das Lock-Objekt stellt sicher, dass jeweils nur ein Thread den synchronisierten Block ausführen kann.Tipps und bewährte Praktiken
java.util.concurrentverwenden, wie z.B.ConcurrentHashMap, die eine integrierte Synchronisierung bieten.volatileverwenden, um die Sichtbarkeit sicherzustellen.