Synchronizace v Java
Co je to Synchronizace v Java?
In Java, synchronizace oznaฤuje schopnost ลรญdit pลรญstup vรญce vlรกken k libovolnรฉmu sdรญlenรฉmu prostลedku. Je to ideรกlnรญ moลพnost, kdy chceme povolit pลรญstup ke sdรญlenรฉmu prostลedku pouze jednomu vlรกknu.
Tento pลรญstup k provรกdฤnรญ se obvykle nazรฝvรก โasynchronnรญโ programovรกnรญ. Na tฤchto procesorech jsou takรฉ vlรกkna, coลพ jsou lehkรฉ procesy, kterรฉ mohou provรกdฤt instrukce souฤasnฤ.
Druhy Synchronizace
Existujรญ dva typy metod synchronizace Java:
1) Synchronizace procesลฏ
2) Synchronizace vlรกken.
Pojฤme studovat vlรกkno a Synchronizace procesลฏ podrobnฤ.
Synchronizace procesu: Zvlรกdรก synchronizaci mezi programy. Napลรญklad programy jako `Microsoft Word` a `Acrobat reader` bฤลพรญ jako samostatnรฉ procesy.
Synchronizace vlรกken: Souฤasnรฉ provรกdฤnรญ kritickรฉho zdroje dvฤma nebo vรญce vlรกkny se nazรฝvรก vlรกkno Synchronizace. Mลฏลพete bรฝt dรกle seskupeni k vzรกjemnฤ se vyluฤujรญcรญ komunikaci a komunikaci mezi vlรกkny.
Co je Lock in Java?
Zavลรญt Java je postaven na vnitลnรญ entitฤ znรกmรฉ jako monitor nebo zรกmek. Ke vลกem objektลฏm je pลidruลพen zรกmek. Takลพe vlรกkno, kterรฉ potลebuje konzistentnรญ pลรญstup k polรญm objektu, musรญ zรญskat zรกmek objektu, neลพ k nim pลistoupรญ, a uvolnรญ zรกmek, kdyลพ je prรกce hotovรก. Tรญm je zajiลกtฤno, ลพe ke sdรญlenรฝm datลฏm pลistupuje vลพdy pouze jedno vlรกkno.
Vรญcevlรกknovรฝ program se synchronizacรญ
Vรญcevlรกknovรฝ program je metoda nebo blok chrรกnฤnรฝ pลed ruลกenรญm z jinรฝch vlรกken sdรญlejรญcรญch stejnรฝ zdroj uvedenรฝ pomocรญ klรญฤovรฉho slova `synchronized`.
Pomocรญ synchronizovanรฉ metody
Kaลพdรก metoda, kterรก je deklarovรกna jako synchronizovanรก, je znรกmรก jako synchronizovanรก metoda. Pouลพรญvรก se takรฉ k uzamฤenรญ objektu pro jakรฝkoli sdรญlenรฝ prostลedek. Takลพe, kdyลพ vlรกkno vyvolรก synchronizovanou metodu. Automaticky pลevezme zรกmek pro danรฝ objekt a uvolnรญ jej, kdyลพ dokonฤรญ svลฏj รบkol.
Poznรกmka: Synchronizovanรฉ klรญฤovรฉ slovo nemลฏลพe pracovat s tลรญdami a promฤnnรฝmi. S klรญฤovรฝm slovem lze pouลพรญt pouze metody a bloky.
Proฤ pouลพรญvat Syncronizovanรก metoda?
- Pouลพรญvรก se k uzamฤenรญ objektu pro jakรฉkoli sdรญlenรฉ prostลedky.
- Objekt zรญskรก zรกmek pลi kaลพdรฉm volรกnรญ synchronizovanรฉ metody.
- Zรกmek se neuvolnรญ, dokud vlรกkno nedokonฤรญ svou funkci
Syntaxe:
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();
}
}
Vysvฤtlenรญ Code:
Spusลฅte tento pลรญklad a vลกimnฤte si, ลพe vlรกkno `0` nejprve zรญskรก zรกmek objektu `mathService` a pouลพรญvรก vรฝhradnฤ tento zรกmek, dokud nedokonฤรญ provรกdฤnรญ. Vlรกkno "0" a "1" nenรญ v tomto kรณdu proloลพeno. Vรฝstup je zobrazen nรญลพe.
Vรฝstup:
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
Pouลพitรญ synchronizovanรฉho bloku
Pลedpoklรกdejme, ลพe nechcete synchronizovat celou metodu. Mรญsto toho chcete synchronizovat nฤkolik ลรกdkลฏ kรณdu. V tรฉ dobฤ, Synchronized block pomohl synchronizovat ten vybranรฝ Java kรณd. SyncZรกmky hronized metody jsou pลรญstupnรฉ na metodฤ, zatรญmco zรกmky synchronizovanรฝch blokลฏ jsou pลรญstupnรฉ na objektu.
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 Vysvฤtlenรญ:
Po spuลกtฤnรญ tohoto kรณdu si vลกimnete, ลพe funguje bez jakรฉhokoli ruลกenรญ. V synchronizovanรฉ metodฤ je zรกmek aplikovรกn metodou, ale v synchronizovanรฉm bloku je zรกmek aplikovรกn objektem. Ujistฤte se, ลพe vรฝstup odpovรญdรก nรกsledujรญcรญmu obrรกzku.
Vรฝstup:
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
Vysvฤtlenรญ kรณdu:
Kdyลพ tento kรณd spustรญte, vลกimnete si, ลพe funguje bez ruลกenรญ, coลพ jsme oฤekรกvali. V synchronizovanรฉ metodฤ je zรกmek aplikovรกn metodou, ale v metodฤ synchronizovanรฉho bloku je zรกmek aplikovรกn objektem.
Pouลพitรญ statickรฉ synchronizace
In Java synchronizace, pokud existuje vรญce neลพ jeden objekt, dvฤ vlรกkna mohou zรญskat zรกmky a vstoupit do synchronizovanรฉho bloku nebo bloku se samostatnรฝm zรกmkem pro kaลพdรฝ objekt. Aby se tomu zabrรกnilo, lze pouลพรญt statickou synchronizaci. Syncpลed statickรฝmi metodami budou pouลพita klรญฤovรก slova s โโhronizovanou hodnotou.
Poznรกmka: Pลi statickรฉ synchronizaci je pลรญstup k zรกmku na tลรญdฤ, nikoli na objektu a metodฤ.
Code demonstrovat problรฉm zamykรกnรญ vรญce objektลฏ
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();
}
}
Vysvฤtlenรญ kรณdu:
Kdyลพ vytvoลรญme dalลกรญ instanci `MathService`, zavedeme interferenci ve vlรกknech, protoลพe budou proloลพena dvฤma objekty. Vลกimnฤte si, ลพe vlรกkno `0` a vlรกkno `2` jsou proklรกdรกny tฤmito dvฤma objekty, zatรญmco vlรกkna `1` a `3` jsou proklรกdรกny tฤmito dvฤma objekty.
Vรฝstup:
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
Stejnรฝ kรณd pomocรญ synchronizovanรฉ statickรฉ metody
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();
}
}
Spusลฅte vรฝลกe uvedenรฝ kรณd a vลกimnฤte si, ลพe jsme nynรญ odstranili interferenci vlรกken. Vรฝstup kรณdu je uveden nรญลพe.
Vรฝstup:
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
Vรฝhody pouลพitรญ synchronizace
Zde jsou vรฝhody pลi prรกci se soubฤลพnรฝmi aplikacemi:
- Hlavnรญm cรญlem synchronizace v Java je zabrรกnit nekonzistentnรญm datลฏm tรญm, ลพe zabrรกnรญ interferenci vlรกken.
- Synchronizovanรฉ klรญฤovรฉ slovo in Java poskytuje zamykรกnรญ, kterรฉ zajiลกลฅuje vzรกjemnฤ se vyluฤujรญcรญ pลรญstup ke sdรญlenรฉmu zdroji a zabraลuje zรกvodลฏm v datech.
- Zabraลuje takรฉ zmฤnฤ poลadรญ pลรญkazลฏ kรณdu pomocรญ kompilรกtor, coลพ mลฏลพe zpลฏsobit jemnรฝ soubฤลพnรฝ problรฉm, pokud nepouลพรญvรกme nestรกlรก nebo synchronizovanรก klรญฤovรก slova.
- Syncklรญฤovรฉ slovo hronized ฤte data z hlavnรญ pamฤti neลพ z cache a kdyลพ uvolnรญ zรกmek.
- Takรฉ vyprรกzdnรญ operace zรกpisu z hlavnรญ pamฤti, ฤรญmลพ eliminuje chyby nekonzistence pamฤti.
Nevรฝhody Synchronizaฤnรญ mechanismus
Syncronizaฤnรญ mechanismy majรญ ลกpatnรฝ vรฝkon.
Napลรญklad
- Pลedpoklรกdejme, ลพe existuje pฤt procesลฏ, A1, A2, A3, A4 a A5.
- ฤekajรญ, aลพ sdรญlenรฉ prostลedky pลistupujรญ k jednomu vlรกknu najednou.
- Vลกechny procesy ฤekajรญ, takลพe poslednรญ ve frontฤ musรญ ฤekat, dokud nebudou dokonฤeny vลกechny ostatnรญ procesy.
Shrnutรญ
- Synchronizace oznaฤuje schopnost ลรญdit pลรญstup vรญce vlรกken k libovolnรฉmu sdรญlenรฉmu prostลedku.
- Java mรก dva typy metod synchronizace: 1) Synchronizace procesลฏ a 2) Synchronizace vlรกken.
- Zavลรญt Java je postaven na vnitลnรญ entitฤ znรกmรฉ jako monitor nebo zรกmek.
- Vรญcevlรกknovรฝ program je metoda nebo blok chrรกnฤnรฝ pลed ruลกenรญm z jinรฝch vlรกken sdรญlejรญcรญch stejnรฝ zdroj oznaฤenรฝ pomocรญ klรญฤovรฉho slova `synchronized`.
- Kaลพdรก metoda, kterรก je deklarovรกna jako synchronizovanรก, je znรกmรก jako synchronizovanรก metoda.
- In Java, synchronizovanรฉ zรกmky metod jsou pลรญstupnรฉ na metodฤ, zatรญmco synchronizovanรฉ blokovรฉ zรกmky jsou pลรญstupnรฉ na objektu.
- Pลi statickรฉ synchronizaci je pลรญstup k zรกmku na tลรญdฤ, nikoli na objektu a metodฤ.
- Hlavnรญm cรญlem synchronizace v Java je zabrรกnit nekonzistentnรญm datลฏm tรญm, ลพe zabrรกnรญ interferenci vlรกken.
- Nejvฤtลกรญ nevรฝhodou tรฉto metody je, ลพe vลกechny procesy ฤekajรญ, takลพe poslednรญ ve frontฤ musรญ ฤekat, dokud nebudou dokonฤeny vลกechny ostatnรญ procesy.
