Architektura wątków i synchronizacja w Javie: od procesora do JVM
Kod Java kompiluje się do bajtkodu, który JVM przekształca w instrukcje maszynowe procesora. Każde rdzenie procesora wykonuje instrukcje sekwencyjnie: w jednym takcie przetwarza prostą operację, taką jak przesunięcie bitu w rejestrze. Rejestry to superszybkie komórki pamięci do przechowywania liczb, adresów i danych.
Współczesne procesory wykorzystują architekturę superskalarową. Hyper-Threading pozwala jednemu sprzętowemu wątkowi wykonywać 2–6 instrukcji na takt, tworząc iluzję wielu logicznych wątków na rdzeniu poprzez szybkie przełączanie kontekstu.
Liczba jednocześnie wykonywanych wątków jest ograniczona liczbą rdzeni. Wątki dzielą pamięć heap, gdzie przechowywane są obiekty, a każdy wątek ma własny stos (stack) dla zmiennych lokalnych i referencji do obiektów.
Race Condition i struktura pamięci
Race Condition występuje, gdy kilka wątków jednocześnie odczytuje i modyfikuje ten sam obiekt w heap. Wynik jest nieprzewidywalny: zależy od kolejności operacji „odczyt-zmiana-zapis”.
Lokalnie kod często działa poprawnie bez obciążenia, ale w produkcji pod wielowątkowością kolizje ujawniają się nieregularnie. Proces w systemie operacyjnym przydziela wspólną pamięć; wątki w procesie to lekkie jednostki wykonania, konkurujące o zasoby.
Mechanizmy synchronizacji: wait/notify i monitory
Każdy obiekt w Javie ma wbudowany monitor (lock). Blok synchronized przejmuje monitor obiektu, zapewniając:
- Mutual Exclusion: tylko jeden wątek wykonuje kod wewnątrz bloku.
- Visibility: zmiany są widoczne dla innych wątków po wyjściu z bloku (z wsparciem
volatile).
Monitor zawiera:
- Entry Set: kolejka wątków czekających na przejęcie.
- Wait Set: wątki w stanie oczekiwania.
Metody wait(), notify(), notifyAll() działają tylko wewnątrz bloku synchronized tego samego obiektu, w przeciwnym razie — IllegalMonitorStateException.
wait(): przenosi wątek do Wait Set.notify(): budzi losowy wątek (ryzyko lost wakeup).notifyAll(): budzi wszystkie wątki (preferowane).
Statyczne metody synchronized blokują monitor klasy (Class), nie kolidując z metodami instancyjnymi (this).
Zaawansowane blokady: ReentrantLock i Semaphore
Dla elastycznej kontroli użyj java.util.concurrent.locks.ReentrantLock:
Lock lock = new ReentrantLock();
lock.lock();
try {
// sekcja krytyczna
} finally {
lock.unlock();
}
Kluczowe metody:
tryLock(): przejęcie bez czekania (false przy niepowodzeniu).tryLock(timeout, unit): czekanie z timeoutem.lockInterruptibly(): przerywalne przejęcie.new ReentrantLock(true): fair locking (FIFO, wolniejsze).
Semaphore ogranicza dostęp:
Semaphore sem = new Semaphore(3); // 3 pozwolenia
sem.acquire(); // przejęcie
sem.release(); // zwolnienie
Problemy wielowątkowości: Deadlock i Livelock
Deadlock: cykliczna zależność blokad. Wątek A trzyma lock1, czeka na lock2; wątek B — odwrotnie. System zawiesza się.
Unikaj:
- Blokuj w stałej kolejności.
- Używaj timeoutów.
- Minimalizuj zagnieżdżone blokady.
Livelock: wątki aktywne, ale nie postępują. Przykład: dwa wątki ustępują sobie zasobów w pętli, obciążając CPU bez postępu.
Synchronność vs asynchroniczność w wątkach
Metoda synchroniczna blokuje wątek na I/O (np. zapytanie do bazy danych): wątek bezczynny do odpowiedzi.
Asynchroniczna używa CompletableFuture — kontenera dla odroczonego wyniku (pending, completed, failed).
Łańcuchy operacji:
thenApply(): transformacja wyniku.thenCompose(): kompozycja z innym Future.thenAccept(): konsumpcja bez zwrotu.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "result")
.thenApply(s -> s.toUpperCase())
.thenAccept(System.out::println);
To zwalnia wątek do innych zadań, zwiększając przepustowość w środowisku wielowątkowym.
Co ważne
- Każde jądro wykonuje jeden sprzętowy wątek; Hyper-Threading emuluje wielość.
- Race Condition od współdzielonego heap; synchronizacja gwarantuje mutual exclusion i visibility.
notifyAll()preferowane przednotify()dla uniknięcia lost wakeup.- ReentrantLock rozszerza
synchronized: timeouty, przerwania, fairness. - CompletableFuture buduje asynchroniczne potoki bez blokowania wątków.
— Editorial Team
Brak komentarzy.