Sobes.tech
Middle+

Jak działa mechanizm synchronizacji 'synchronized' w języku Java od kuchni?

sobes.tech AI

Odpowiedź od AI

Mechanizm synchronized w Javie opiera się na koncepcji monitorów (obiektów monitorowych). Każdemu obiektowi w Javie przypisany jest monitor.

Gdy wątek wchodzi do zablokowanego sekcji lub metody, próbuje przejąć monitor odpowiedniego obiektu. Jeśli monitor jest wolny, wątek go przejmuje i kontynuuje wykonanie. Jeśli monitor jest zajęty przez inny wątek, bieżący wątek zostaje zablokowany i przechodzi w stan oczekiwania, aż monitor zostanie zwolniony.

Gdy wątek opuszcza zablokowany sekcję lub metodę (czy to przez pomyślne zakończenie, czy przez wyrzucenie wyjątku), zwalnia monitor.

Wewnątrz monitora zaimplementowane są:

  1. Wzajemne wykluczenie (Mutual Exclusion): Tylko jeden wątek może posiadać monitor obiektu w danym momencie. Zapewnia to, że tylko jeden wątek może wykonywać zsynchronizowany kod dla tego obiektu.
  2. Oczekiwanie i powiadomienie (Waiting and Notification): Monitor zawiera zestaw powiązanych metod wait(), notify() i notifyAll(). Metody te pozwalają wątkom posiadającym monitor na tymczasowe zwolnienie go i przejście w stan oczekiwania, a następnie na powiadomienie innych wątków o możliwości kontynuowania pracy.

Implementacja na poziomie niskim obejmuje:

  • Instrukcja monitorenter: Wykonywana przy wejściu do zablokowanego sekcji lub metody. Próbuje przejąć monitor obiektu.
  • Instrukcja monitorexit: Wykonywana przy wyjściu z zablokowanej sekcji lub metody (zarówno w przypadku normalnego zakończenia, jak i wyrzucenia wyjątku). Zwolnienie monitora obiektu.

Instrukcje te są częścią kodu bajtowego Java i są obsługiwane przez maszynę wirtualną Java (JVM). JVM używa natywnych mechanizmów systemu operacyjnego (np. mutexów, semaforów) do zarządzania monitorami i blokadą/odblokowaniem wątków.

Przyjęcie monitora może być zaimplementowane na poziomie obiektu (dla metod i bloków instancji) lub na poziomie klasy (dla metod i bloków statycznych), używając obiektu Class jako blokady.

Przykład użycia:

public class Counter {
    private int count = 0;

    public synchronized void increment() { // Zsynchronizowana metoda
        count++;
    }

    public void decrement() {
        synchronized (this) { // Zsynchronizowany blok
            count--;
        }
    }

    public static synchronized void staticMethod() { // Statyczna metoda zsynchronizowana
        // ...
    }
}

Tabela metod klasy Object związanych z monitorami:

Metoda Opis
wait() Wątek posiadający monitor tymczasowo go zwalnia i przechodzi w stan oczekiwania.
notify() Powiadamia jeden z oczekujących wątków, że może próbować przejąć monitor i kontynuować pracę.
notifyAll() Powiadamia wszystkie oczekujące wątki.