Synchronisering i Java
Hva er Synchronisering i Java?
In Java, refererer synkronisering til muligheten til å kontrollere tilgangen til flere tråder til en hvilken som helst delt ressurs. Det er et ideelt alternativ der vi ønsker å la bare én tråd få tilgang til den delte ressursen.
Denne tilnærmingen til utførelse blir vanligvis referert til som "asynkron" programmering. Det er også tråder på disse prosessorene, som er lette prosesser som kan utføre instruksjoner samtidig.
Typer av Synchronisering
Det er to typer synkroniseringsmetoder i Java:
1) Prosesssynkronisering
2) Trådsynkronisering.
La oss studere tråd og Prosesssynkronisering i detalj.
Prosesssynkronisering: Den administrerer synkronisering mellom programmer. For eksempel programmer som `Microsoft Word` og `Acrobat reader` kjøres som individuelle prosesser.
Trådsynkronisering: Samtidig utførelse av den kritiske ressursen av to eller flere tråder kalles tråd Synchronisering. Du kan grupperes videre til gjensidig utelukkende kommunikasjon og kommunikasjon mellom tråder.
Hva er Lock in Java?
Låse inn Java er bygget rundt en intern enhet kjent som en monitor eller låsen. Alle objektene har en lås knyttet til seg. Så tråden som trenger konsekvent tilgang til et objekts felt, må skaffe seg objektets lås før den får tilgang til dem, og den frigjør låsen når arbeidet er ferdig. Dette sikrer at bare én tråd får tilgang til de delte dataene om gangen.
Flertråds program med synkronisering
Et flertråds program er en metode eller blokk beskyttet mot forstyrrelser fra andre tråder som deler den samme ressursen som er angitt med nøkkelordet "synkronisert".
Bruker den synkroniserte metoden
Enhver metode som er erklært som synkronisert er kjent som en synkronisert metode. Den brukes også til å låse et objekt for enhver delt ressurs. Så når en tråd påkaller en synkronisert metode. Den tar automatisk låsen for det objektet i besittelse og slipper den når den har fullført oppgaven.
OBS: Det synkroniserte nøkkelordet kan ikke fungere med klasser og variabler. Bare metoder og blokker kan brukes med nøkkelordet.
Hvorfor bruke Synchronisert metode?
- Den brukes til å låse et objekt for eventuelle delte ressurser.
- Objektet får låsen hver gang den synkroniserte metoden kalles.
- Låsen frigjøres ikke før tråden fullfører sin funksjon
Syntaks:
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(); } }
Forklaring av kode:
Kjør dette eksemplet og observer at tråden `0` får låsen til `mathService`-objektet først og bruker denne låsen utelukkende til den er fullført. Tråd "0" og "1" er ikke sammenflettet i denne koden. Utgangen er som vist nedenfor.
Utgang:
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
Bruke en synkronisert blokk
La oss anta at du ikke vil synkronisere hele metoden. I stedet vil du synkronisere noen få linjer med kode. På den tiden var Synchronisert blokk bidro til å synkronisere den valgte Java kode. Synchroniserte metodelåser får tilgang på metoden, mens synkroniserte blokklåser får tilgang 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(); } }
Kodeforklaring:
Når du kjører denne koden, vil du merke at den fungerer uten forstyrrelser. I den synkroniserte metoden brukes låsen av metoden, men i den synkroniserte blokken brukes låsen av objektet. Sørg for at utgangen er som vist nedenfor.
Utgang:
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
Forklaring av kode:
Når du kjører denne koden, vil du merke at den fungerer uten forstyrrelser, noe vi forventet. I den synkroniserte metoden brukes låsen av metoden, men i den synkroniserte blokkeringsmetoden brukes låsen av objektet.
Bruker statisk synkronisering
In Java synkronisering, hvis det er mer enn ett objekt, kan to tråder skaffe låsene og gå inn i en synkronisert blokk eller blokk, med en separat lås for hvert objekt. For å unngå dette kan statisk synkronisering brukes. Synchroniserte søkeord vil bli brukt før statiske metoder.
OBS: Ved statisk synkronisering er låstilgang på klassen, ikke objektet og metoden.
Kode for å demonstrere problemet med låsing av flere objekter
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(); } }
Forklaring av kode:
Når vi oppretter en annen forekomst av `MathService`, introduserer vi interferens i trådene ettersom de vil bli sammenflettet med de to objektene. Merk at tråd `0` og tråd `2` er sammenflettet med de to objektene, mens tråd `1` og `3` er sammenflettet med de to objektene.
Utgang:
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
Samme kode ved hjelp av synkronisert statisk metode
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(); } }
Kjør koden ovenfor og merk at vi nå har eliminert trådinterferens. Utgangen av koden er vist nedenfor.
Utgang:
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
Fordeler med å bruke synkronisering
Her er fordelene ved å jobbe med samtidige applikasjoner:
- Hovedmålet med synkronisering i Java er å forhindre inkonsistente data ved å forhindre trådinterferens.
- Det synkroniserte nøkkelordet i Java gir låsing, som sikrer gjensidig utelukkende tilgang til den delte ressursen og forhindrer dataras.
- Det forhindrer også omorganisering av kodesetninger av kompilatoren, som kan forårsake et subtilt samtidig problem hvis vi ikke bruker flyktige eller synkroniserte søkeord.
- Synchronisert nøkkelord leser data fra hovedminnet enn cache og når det slipper låsen.
- Den fjerner også skriveoperasjoner fra hovedminnet, og eliminerer minneinkonsistensfeil.
Ulemper med Synchroniseringsmekanisme
Synchroniseringsmekanismer har dårlig ytelse.
For eksempel
- Anta at det er fem prosesser, A1, A2, A3, A4 og A5.
- De venter på at de delte ressursene skal få tilgang til én tråd om gangen.
- Alle prosesser holdes ventende, så den siste i køen må vente til alle andre prosesser er fullført.
Sammendrag
- Synchronisering refererer til muligheten til å kontrollere tilgangen til flere tråder til en hvilken som helst delt ressurs.
- Java har to typer synkroniseringsmetoder: 1) Prosesssynkronisering og 2) Trådsynkronisering.
- Låse inn Java er bygget rundt en intern enhet kjent som en monitor eller låsen.
- Et multithreaded-program er en metode eller blokk beskyttet mot forstyrrelser fra andre tråder som deler den samme ressursen som er angitt med nøkkelordet "synkronisert".
- Enhver metode som er erklært som synkronisert er kjent som en synkronisert metode.
- In Java, synkroniserte metodelåser får tilgang på metoden, mens synkroniserte blokklåser får tilgang til objektet.
- Ved statisk synkronisering er låstilgang på klassen, ikke objektet og metoden.
- Hovedmålet med synkronisering i Java er å forhindre inkonsistente data ved å forhindre trådinterferens.
- Den største ulempen med denne metoden er at alle prosesser holdes i vente, så den siste i køen må vente til alle andre prosesser er fullført.