Direkt zum Inhalt
Urkunden
Java SchlüsselwörterJava-ArraysJava Objektorientierte ProgrammierungJava File HandlingEinführung in JavaGrundlagen der Java-Sprache

synchronized Schlüsselwort in Java

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 void synchronizedMethod() {
    // method code
}

Synchronisierter Block

public void method() {
    synchronized (object) {
        // synchronized code
    }
}
  • object: Das Objekt, auf das synchronisiert werden soll. Dies ist normalerweise die aktuelle Instanz (this) oder ein bestimmtes Objekt.

Beispiele

Beispiel 1: Synchronisierte Methode

public class Counter {
    private int count = 0;

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

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Counter counter = new Counter();

        // Create multiple threads to increment the counter
        Thread t1 = new Thread(() -> counter.increment());
        Thread t2 = new Thread(() -> counter.increment());

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + counter.getCount());
    }
}

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

public class SynchronizedBlockExample {
    private final Object lock = new Object();
    private int count = 0;

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        SynchronizedBlockExample example = new SynchronizedBlockExample();

        // Create multiple threads to increment the counter
        Thread t1 = new Thread(() -> example.increment());
        Thread t2 = new Thread(() -> example.increment());

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + example.getCount());
    }
}

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.
private volatile boolean flag;
  • 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.
public static synchronized void staticMethod() {
    // method code
}
  • 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.

Java Grundlagen lernen

Baue deine Java-Kenntnisse von Grund auf auf und beherrsche Programmierkonzepte.
Kostenloses Lernen beginnen