Synchronisering i Java
Vad är Synchronisering i Java?
In Java, synkronisering syftar på möjligheten att kontrollera åtkomsten av flera trådar till valfri delad resurs. Det är ett idealiskt alternativ där vi vill tillåta endast en tråd att komma åt den delade resursen.
Detta tillvägagångssätt för exekvering brukar kallas "asynkron" programmering. Det finns också trådar om dessa processorer, som är lätta processer som kan exekvera instruktioner samtidigt.
Typer av Synchronisering
Det finns två typer av synkroniseringsmetoder i Java:
1) Processsynkronisering
2) Trådsynkronisering.
Låt oss studera tråd och Processsynkronisering i detalj.
Processsynkronisering: Den hanterar synkronisering mellan program. Till exempel program som `Microsoft Word` och `Acrobat reader` körs som individuella processer.
Trådsynkronisering: Den samtidiga exekveringen av den kritiska resursen av två eller flera trådar kallas tråd Synchronisering. Du kan grupperas ytterligare för att ömsesidigt utesluta och kommunikation mellan trådar.
Vad är Lock in Java?
Låsa in Java är byggd kring en intern enhet som kallas en monitor eller låset. Alla objekt har ett lås kopplat till dem. Så tråden som behöver konsekvent åtkomst till ett objekts fält måste skaffa objektets lås innan den kommer åt dem, och den släpper låset när arbetet är klart. Detta säkerställer att endast en tråd kommer åt de delade data åt gången.
Flertrådigt program med synkronisering
Ett flertrådigt program är en metod eller ett block som är skyddat från störningar från andra trådar som delar samma resurs som anges med nyckelordet "synkroniserat".
Använder den synkroniserade metoden
Varje metod som deklareras som synkroniserad är känd som en synkroniserad metod. Det används också för att låsa ett objekt för alla delade resurser. Så, när en tråd anropar en synkroniserad metod. Den tar automatiskt besittning av låset för det objektet och släpper det när det har avslutat sin uppgift.
Obs: Det synkroniserade nyckelordet kan inte fungera med klasser och variabler. Endast metoder och block kan användas med nyckelordet.
Varför använda Synchroniserad metod?
- Den används för att låsa ett objekt för alla delade resurser.
- Objektet får låset när den synkroniserade metoden anropas.
- Låset släpper inte förrän tråden slutfört sin funktion
Syntax:
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(); } }
Förklaring av kod:
Kör det här exemplet och observera att tråden `0` får låset för `mathService`-objektet först och använder detta lås exklusivt tills den har slutfört exekveringen. Tråd "0" och "1" är inte interfolierade i denna kod. Utgången är som visas nedan.
Produktion:
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
Använder ett synkroniserat block
Låt oss anta att du inte vill synkronisera hela metoden. Istället vill du synkronisera några rader kod. På den tiden, den Synchronized block hjälpte till att synkronisera det valda Java koda. Synchroniserade metodlås nås på metoden, medan synkroniserade blocklås nås på objektet.
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(); } }
Kodförklaring:
När du kör den här koden kommer du att notera att den fungerar utan störningar. I den synkroniserade metoden tillämpas låset av metoden, men i det synkroniserade blocket tillämpas låset av objektet. Se till att utgången är som visas nedan.
Produktion:
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
Förklaring av kod:
När du kör den här koden kommer du att notera att den fungerar utan störningar, vilket vi förväntade oss. I den synkroniserade metoden tillämpas låset av metoden, men i den synkroniserade blockmetoden tillämpas låset av objektet.
Använder statisk synkronisering
In Java synkronisering, om det finns mer än ett objekt, kan två trådar förvärva låsen och gå in i ett synkroniserat block eller block, med ett separat lås för varje objekt. För att undvika detta kan statisk synkronisering användas. Synchroniserade nyckelord kommer att användas före statiska metoder.
Obs: I statisk synkronisering är låsåtkomst på klassen, inte objektet och metoden.
Kod för att visa problemet med låsning av flera 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(); } }
Förklaring av kod:
När vi skapar en annan instans av `MathService` introducerar vi interferens i trådarna eftersom de kommer att interfolieras med de två objekten. Observera att tråd `0` och tråd `2` är sammanflätade med de två objekten, medan tråd `1` och `3` är sammanflätade med de två objekten.
Produktion:
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
Samma kod med synkroniserad statisk metod
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(); } }
Kör ovanstående kod och notera att vi nu har eliminerat trådstörningar. Utdata från koden visas nedan.
Produktion:
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
Fördelar med att använda synkronisering
Här är fördelarna med att arbeta med samtidiga applikationer:
- Huvudsyftet med synkronisering i Java är att förhindra inkonsekventa data genom att förhindra trådstörningar.
- Det synkroniserade nyckelordet i Java tillhandahåller låsning, vilket säkerställer ömsesidigt uteslutande åtkomst till den delade resursen och förhindrar dataracing.
- Det förhindrar också omordning av kodsatser av kompilator, vilket kan orsaka ett subtilt samtidig problem om vi inte använder flyktiga eller synkroniserade sökord.
- Synchronized nyckelord läser data från huvudminnet än cache och när det släpper låset.
- Det rensar också skrivoperationer från huvudminnet, vilket eliminerar minnesinkonsekvensfel.
Nackdelar med Synchroniseringsmekanism
Synchronisering Mekanismer har dålig prestanda.
Till exempel
- Antag att det finns fem processer, A1, A2, A3, A4 och A5.
- De väntar på att de delade resurserna ska komma åt en tråd i taget.
- Alla processer hålls väntande, så den sista i kön måste vänta tills alla andra processer är klara.
Sammanfattning
- Synchronisering hänvisar till möjligheten att kontrollera åtkomsten av flera trådar till valfri delad resurs.
- Java har två typer av synkroniseringsmetoder: 1) Processsynkronisering och 2) Trådsynkronisering.
- Låsa in Java är byggd kring en intern enhet som kallas en monitor eller låset.
- Ett flertrådigt program är en metod eller ett block som skyddas från störningar från andra trådar som delar samma resurs som anges med nyckelordet "synkroniserat".
- Varje metod som deklareras som synkroniserad är känd som en synkroniserad metod.
- In Java, synkroniserade metodlås nås på metoden, medan synkroniserade blocklås nås på objektet.
- I statisk synkronisering är låsåtkomst på klassen, inte objektet och metoden.
- Huvudsyftet med synkronisering i Java är att förhindra inkonsekventa data genom att förhindra trådstörningar.
- Den största nackdelen med denna metod är att alla processer hålls i väntan, så den sista i kön måste vänta tills alla andra processer är klara.