Das Schlüsselwort synchronized wurde in Java eingeführt, als die Multithreading-Unterstützung eingebaut wurde, um exklusiven Zugriff auf Codeblöcke oder Methoden aus verschiedenen Threads zu garantieren. Historisch gesehen ist dies die Antwort von Java auf klassische Probleme wie Race Conditions und Dateninkonsistenz, die beim gleichzeitigen Zugriff auf gemeinsame Daten aus verschiedenen Threads entstehen.
Problem bei der Arbeit mit Multithreading ist die Gewährleistung der "Atomarität" von Operationen und die Verhinderung von widersprüchlichen Änderungen an Objektzuständen. Eine falsche Handhabung von synchronized kann zu Deadlocks, Leistungsabfällen oder sogar zu fehlender Synchronisation bei falscher Wahl des Monitorobjekts führen.
Lösung – verwenden Sie das Schlüsselwort synchronized für eine Methode oder einen Codeblock, wo sichergestellt werden muss, dass immer nur ein Thread diesen Abschnitt gleichzeitig ausführt. Wählen Sie das Synchronisationsobjekt sorgfältig aus, vermeiden Sie lange kritische Abschnitte, und verwenden Sie für komplexere Aufgaben spezielle Klassen aus dem Paket java.util.concurrent.
Beispielcode:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } // Synchronisation nur für einen Codeabschnitt auf einem separaten Objekt: private final Object lock = new Object(); public void complexIncrement() { synchronized (lock) { // kritischer Abschnitt count++; } }
Wichtige Merkmale:
Was ist der Unterschied zwischen einer synchronized-Methode und einem synchronized-Block?
Eine synchronisierte Methode blockiert den "Monitor" des Objekts (oder der Klasse, wenn die Methode statisch ist), während ein synchronisierter Block es ermöglicht, das Monitorobjekt explizit anzugeben, was größere Flexibilität bietet.
Was passiert, wenn in einem Objekt verschiedene Methoden synchronisiert sind?
Wenn beide Methoden mit synchronized gekennzeichnet sind (nicht statisch), verwenden beide das Objekt selbst (this) als Monitor. Ein Thread kann keinen der Methoden betreten, während ein anderer sich darin befindet.
Kann man statische und reguläre Methoden synchronisieren? Wie entsperren sie sich relativ zueinander?
Statische Methoden verwenden den Monitor der Klasse selbst (das Class-Objekt), reguläre verwenden das Objekt der Instanz. Daher blockieren sich ein statischer synchronized-Methode und eine reguläre synchronized-Methode nicht gegenseitig.
Ein Entwickler synchronisiert Methoden verschiedener Objekte, verwendet jedoch überall denselben String als Monitor. Infolgedessen treten Verlangsamungen und "zufällige" Deadlocks aufgrund der Wiederverwendung von Strings aus dem Pool auf.
Vorteile:
Nachteile:
Synchronisation auf einem privaten finalen Objekt, das nur innerhalb der Klasse erstellt wird (private final Object lock), und die kritischen Abschnitte sind minimal in der Zeit.
Vorteile:
Nachteile: