Historia pytania:
Od momentu pojawienia się Javy, programiści spotkali się z problemem konkurencyjnego dostępu do wspólnych zasobów. W celu rozwiązania wprowadzono wysokopoziomowe prymitywy synchronizacji, z których najważniejszym jest modyfikator kluczowy synchronized.
Problem:
Bez synchronizacji w aplikacjach wielowątkowych dzielone zasoby mogą być uszkodzone: pojawia się wyścig danych (data race), a stan obiektu staje się nieprzewidywalny.
Rozwiązanie:
synchronized pozwala zorganizować monitor dla metody lub bloku kodu, zapewniając dostęp tylko jednemu wątkowi w danym momencie do sekcji krytycznej. Synchronizacja wątku może być realizowana na poziomie metody lub bloku.
Przykład blokady obiektu:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }
Bloki również można synchronizować:
public void safeIncrement() { synchronized(this) { count++; } }
Kluczowe cechy:
Czym różni się synchronized-metoda od synchronized-bloku?
synchronized-metoda blokuje całą metodę dla bieżącego obiektu (this) lub klasy (jeśli metoda jest statyczna). Blok pozwala synchronizować tylko potrzebny fragment kodu i wybierać dowolny obiekt do blokady.
Czy dwa różne wątki mogą jednocześnie wejść do dwóch różnych synchronized-metod jednego obiektu?
Nie, jeśli metody są synchronizowane na tym samym monitorze (this). Jeśli używają różnych monitorów, to tak.
Czy modyfikator synchronized wpływa na widoczność zmiennych między wątkami?
Tak, wejście do synchronized-bloku resetuje pamięci podręczne wątków i aktualizuje wartości zmiennych (relacja happens-before).
Programista synchronizuje statyczne metody klasy na obiekcie instancji, co nie gwarantuje poprawności przy używaniu przez różne instancje.
Plusy:
Minusy:
Wszystkie metody, korzystające ze wspólnego zasobu, są synchronizowane na jednym obiekcie-monitorze, obszar sekcji krytycznej jest minimalny.
Plusy:
Minusy: