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ą:
- 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.
- Oczekiwanie i powiadomienie (Waiting and Notification): Monitor zawiera zestaw powiązanych metod
wait(),notify()inotifyAll(). 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. |