Synchronizacja w Java
Czym jest Synchronizacja w Java?
In Java, synchronizacja odnosi siฤ do moลผliwoลci kontrolowania dostฤpu wielu wฤ tkรณw do dowolnego wspรณลdzielonego zasobu. Jest to idealne rozwiฤ zanie, gdy chcemy zezwoliฤ tylko jednemu wฤ tkowi na dostฤp do wspรณลdzielonego zasobu.
To podejลcie do wykonywania jest zwykle okreลlane jako programowanie `asynchroniczne`. Istniejฤ rรณwnieลผ wฤ tki na tych procesorach, ktรณre sฤ lekkimi procesami, ktรณre mogฤ wykonywaฤ instrukcje jednoczeลnie.
Rodzaje Synchronizacja
Istniejฤ dwa rodzaje metod synchronizacji w Java:
1) Synchronizacja procesรณw
2) Synchronizacja wฤ tkรณw.
Przestudiujmy wฤ tek i Synchronizacja procesรณw szczegรณลowo.
Synchronizacja procesรณw: Zarzฤ dza synchronizacjฤ miฤdzy programami. Na przykลad programy takie jak `Microsoft Word` i `Acrobat reader` dziaลajฤ jako osobne procesy.
Synchronizacja wฤ tkรณw: Rรณwnoczesne wykonywanie zasobu krytycznego przez dwa lub wiฤcej wฤ tkรณw nazywa siฤ wฤ tkiem Synchronizacja. Moลผna dalej pogrupowaฤ w celu komunikacji wzajemnie wykluczajฤ cej siฤ i miฤdzywฤ tkowej.
Co to jest Zablokuj Java?
Zamknij Java jest zbudowany wokรณล wewnฤtrznej jednostki zwanej monitorem lub zamkiem. Z kaลผdym obiektem jest powiฤ zany zamek. Zatem wฤ tek wymagajฤ cy staลego dostฤpu do pรณl obiektu musi uzyskaฤ blokadฤ obiektu przed uzyskaniem do nich dostฤpu i zwolniฤ blokadฤ po zakoลczeniu pracy. Dziฤki temu tylko jeden wฤ tek bฤdzie miaล dostฤp do udostฤpnionych danych w danym momencie.
Program wielowฤ tkowy z synchronizacjฤ
Program wielowฤ tkowy jest metodฤ lub blokiem zabezpieczonym przed zakลรณceniami ze strony innych wฤ tkรณw wspรณลdzielฤ cych ten sam zasรณb, wskazany za pomocฤ sลowa kluczowego `synchronized`.
Korzystanie z metody synchronizowanej
Kaลผda metoda, ktรณra jest zadeklarowana jako synchronized, jest znana jako synchronized Method. Jest ona rรณwnieลผ uลผywana do blokowania obiektu dla dowolnego wspรณลdzielonego zasobu. Tak wiฤc, gdy wฤ tek wywoลuje metodฤ synchronized, automatycznie przejmuje ona blokadฤ dla tego obiektu i zwalnia jฤ , gdy zakoลczy swoje zadanie.
Uwaga: Sลowo kluczowe synchronized nie moลผe dziaลaฤ z klasami i zmiennymi. Tylko metody i bloki mogฤ byฤ uลผywane ze sลowem kluczowym.
Dlaczego warto korzystaฤ z Synchronizowana metoda?
- Sลuลผy do blokowania obiektu dla dowolnych wspรณลdzielonych zasobรณw.
- Obiekt uzyskuje blokadฤ za kaลผdym razem, gdy wywoลana zostanie metoda synchronized.
- Blokada nie zostanie zwolniona, dopรณki gwint nie zakoลczy swojej funkcji
Skลadnia:
Acess_modifiers synchronized return_type method_name (Method_Parameters) {
}
class MathService {
synchronized void getSumOfArray(int[] numbers) {
int sum = 0;
for (int number : numbers) {
System.out.println(Thread.currentThread()
.getName()
+ " adds "
+ sum + " to "
+ number + " to get -> "
+ (sum += number));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Synchronization {
public static void main(String[] args) {
MathService mathService = new MathService();
Thread threadOne = new Thread(() ->
mathService.getSumOfArray(new int[]{10, 11, 12}));
Thread threadTwo = new Thread(() ->
mathService.getSumOfArray(new int[]{20, 21, 22}));
threadOne.start();
threadTwo.start();
}
}
Wyjaลnienie Code:
Uruchom ten przykลad i zaobserwuj, ลผe wฤ tek `0` najpierw pobiera blokadฤ obiektu `mathService` i uลผywa tej blokady wyลฤ cznie do momentu zakoลczenia wykonywania. W tym kodzie wฤ tki โ0โ i โ1โ nie sฤ przeplatane. Dane wyjลciowe sฤ takie, jak pokazano poniลผej.
Wyjลcie:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Korzystanie z bloku synchronizowanego
Zaลรณลผmy, ลผe nie chcesz synchronizowaฤ caลej metody. Zamiast tego chcesz zsynchronizowaฤ kilka linii kodu. W tym czasie Syncblok hronic pomรณgล zsynchronizowaฤ wybrane Java kod. SyncDostฤp do blokad metod synchronicznych odbywa siฤ na poziomie metody, natomiast dostฤp do blokad blokรณw synchronicznych odbywa siฤ na poziomie obiektu.
class MathService {
void getSumOfArray(int[] numbers) {
synchronized (this){
int sum = 0;
for (int number : numbers) {
System.out.println(Thread.currentThread()
.getName()
+ " adds "
+ sum + " to "
+ number + " to get -> "
+ (sum += number));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class Synchronization {
public static void main(String[] args) {
MathService mathService = new MathService();
Thread threadOne = new Thread(() ->
mathService.getSumOfArray(new int[]{10, 11, 12}));
Thread threadTwo = new Thread(() ->
mathService.getSumOfArray(new int[]{20, 21, 22}));
threadOne.start();
threadTwo.start();
}
}
Code Wyjaลnienie:
Po uruchomieniu tego kodu zauwaลผysz, ลผe dziaลa on bez ลผadnych zakลรณceล. W metodzie synchronized blokada jest stosowana przez metodฤ, ale w bloku synchronized blokada jest stosowana przez obiekt. Upewnij siฤ, ลผe dane wyjลciowe sฤ takie, jak pokazano poniลผej.
Wyjลcie:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Wyjaลnienie kodu:
Gdy uruchomisz ten kod, zauwaลผysz, ลผe dziaลa on bez zakลรณceล, czego oczekiwaliลmy. W metodzie synchronized blokada jest stosowana przez metodฤ, ale w metodzie synchronized block blokada jest stosowana przez obiekt.
Korzystanie ze statycznej synchronizacji
In Java synchronizacja, jeลli jest wiฤcej niลผ jeden obiekt, dwa wฤ tki mogฤ nabyฤ blokady i wejลฤ do zsynchronizowanego bloku lub bloku, z oddzielnฤ blokadฤ dla kaลผdego obiektu. Aby tego uniknฤ ฤ, moลผna uลผyฤ statycznej synchronizacji. Synchronizowane sลowa kluczowe bฤdฤ uลผywane przed metodami statycznymi.
Uwaga: W przypadku synchronizacji statycznej dostฤp do blokad jest moลผliwy na poziomie klasy, a nie obiektu i metody.
Code aby zademonstrowaฤ problem blokowania wielu obiektรณw
class MathService {
synchronized void getSumOfArray(int[] numbers) {
int sum = 0;
for (int number : numbers) {
System.out.println(Thread.currentThread()
.getName()
+ " adds "
+ sum + " to "
+ number + " to get -> "
+ (sum += number));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Synchronization {
public static void main(String[] args) {
MathService mathService = new MathService();
MathService mathService1 = new MathService();
Thread threadOne = new Thread(() ->
mathService.getSumOfArray(new int[]{10, 11, 12}));
Thread threadTwo = new Thread(() ->
mathService.getSumOfArray(new int[]{20, 21, 22}));
Thread threadThree = new Thread(() ->
mathService1.getSumOfArray(new int[]{10, 11, 12}));
Thread threadFour = new Thread(() ->
mathService1.getSumOfArray(new int[]{20, 21, 22}));
threadOne.start();
threadTwo.start();
threadThree.start();
threadFour.start();
}
}
Wyjaลnienie kodu:
Kiedy tworzymy kolejnฤ instancjฤ `MathService`, wprowadzamy interferencjฤ w wฤ tkach, poniewaลผ bฤdฤ one przeplatane z dwoma obiektami. Zauwaลผ, ลผe wฤ tki `0` i `2` sฤ przeplatane z tymi dwoma obiektami, podczas gdy wฤ tki `1` i `3` sฤ przeplatane z tymi dwoma obiektami.
Wyjลcie:
Thread-0 adds 0 to 10 to get -> 10 Thread-2 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-2 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-3 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-3 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63 Thread-3 adds 41 to 22 to get -> 63
Ten sam kod wykorzystujฤ cy metodฤ statycznฤ synchronizowanฤ
class MathService {
synchronized static void getSumOfArray(int[] numbers) {
int sum = 0;
for (int number : numbers) {
System.out.println(Thread.currentThread()
.getName()
+ " adds "
+ sum + " to "
+ number + " to get -> "
+ (sum += number));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Synchronization {
public static void main(String[] args) {
MathService mathService = new MathService();
MathService mathService1 = new MathService();
Thread threadOne = new Thread(() ->
mathService.getSumOfArray(new int[]{10, 11, 12}));
Thread threadTwo = new Thread(() ->
mathService.getSumOfArray(new int[]{20, 21, 22}));
Thread threadThree = new Thread(() ->
mathService1.getSumOfArray(new int[]{10, 11, 12}));
Thread threadFour = new Thread(() ->
mathService1.getSumOfArray(new int[]{20, 21, 22}));
threadOne.start();
threadTwo.start();
threadThree.start();
threadFour.start();
}
}
Uruchom powyลผszy kod i zauwaลผ, ลผe wyeliminowaliลmy teraz zakลรณcenia wฤ tkรณw. Wynik kodu pokazano poniลผej.
Wyjลcie:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-3 adds 0 to 20 to get -> 20 Thread-3 adds 20 to 21 to get -> 41 Thread-3 adds 41 to 22 to get -> 63 Thread-2 adds 0 to 10 to get -> 10 Thread-2 adds 10 to 11 to get -> 21 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Zalety korzystania z synchronizacji
Oto zalety pracy z wspรณลbieลผnymi aplikacjami:
- Gลรณwnym celem synchronizacji w Java ma na celu zapobieganie niespรณjnym danym poprzez zapobieganie interferencji wฤ tkรณw.
- Sลowo kluczowe synchronized w Java zapewnia blokowanie, ktรณre gwarantuje wzajemnie wyลฤ czny dostฤp do wspรณลdzielonego zasobu i zapobiega wyลcigowi danych.
- Zapobiega takลผe zmianie kolejnoลci instrukcji kodu przez metodฤ kompilator, co moลผe powodowaฤ subtelny problem, jeลli nie uลผyjemy sลรณw kluczowych volatile lub synchronized.
- Synchronized sลowo kluczowe odczytuje dane z pamiฤci gลรณwnej niลผ z pamiฤci podrฤcznej i kiedy zwalnia blokadฤ.
- Oprรณลผnia rรณwnieลผ pamiฤฤ gลรณwnฤ z operacji zapisu, eliminujฤ c bลฤdy niespรณjnoลci pamiฤci.
Wady SyncMechanizm ronizacji
SyncMechanizmy hronizacji majฤ sลabฤ wydajnoลฤ.
Na przykลad
- Zaลรณลผmy, ลผe istnieje piฤฤ procesรณw: A1, A2, A3, A4 i A5.
- Czekajฤ , aลผ udostฤpnione zasoby bฤdฤ miaลy dostฤp do jednego wฤ tku na raz.
- Wszystkie procesy oczekujฤ , wiฤc ostatni w kolejce musi poczekaฤ, aลผ wszystkie inne procesy zostanฤ zakoลczone.
Podsumowanie
- Synchronizacja odnosi siฤ do moลผliwoลci kontrolowania dostฤpu wielu wฤ tkรณw do dowolnego wspรณลdzielonego zasobu.
- Java ma dwa rodzaje metod synchronizacji: 1) Synchronizacja procesรณw i 2) Synchronizacja wฤ tkรณw.
- Zamknij Java jest zbudowany wokรณล wewnฤtrznej jednostki zwanej monitorem lub zamkiem.
- Program wielowฤ tkowy to metoda lub blok zabezpieczony przed zakลรณceniami ze strony innych wฤ tkรณw wspรณลdzielฤ cych ten sam zasรณb, wskazany za pomocฤ sลowa kluczowego `synchronized`.
- Kaลผda metoda zadeklarowana jako synchronizowana jest nazywana metodฤ synchronizowanฤ .
- In JavaDostฤp do blokad metod synchronizowanych uzyskuje siฤ na poziomie metody, natomiast dostฤp do blokad blokรณw synchronizowanych uzyskuje siฤ na poziomie obiektu.
- W przypadku synchronizacji statycznej dostฤp do blokad jest moลผliwy na poziomie klasy, a nie obiektu i metody.
- Gลรณwnym celem synchronizacji w Java ma na celu zapobieganie niespรณjnym danym poprzez zapobieganie interferencji wฤ tkรณw.
- Najwiฤkszฤ wadฤ tej metody jest to, ลผe wszystkie procesy czekajฤ , wiฤc ostatni w kolejce musi poczekaฤ, aลผ wszystkie inne procesy zostanฤ zakoลczone.
