CodeGym /Java-blogg /Tilfeldig /Trådsynkronisering. Den synkroniserte operatøren
John Squirrels
Nivå
San Francisco

Trådsynkronisering. Den synkroniserte operatøren

Publisert i gruppen
Hei! I dag vil vi fortsette å vurdere funksjonene til flertrådsprogrammering og snakke om trådsynkronisering. Trådsynkronisering.  Den synkroniserte operatøren - 1

Hva er synkronisering i Java?

Utenfor programmeringsdomenet innebærer det en ordning som lar to enheter eller programmer fungere sammen. En smarttelefon og datamaskin kan for eksempel synkroniseres med en Google-konto, og en nettsidekonto kan synkroniseres med sosiale nettverkskontoer slik at du kan bruke dem til å logge på. Trådsynkronisering har en lignende betydning: det er en ordning der tråder samhandler med hverandre. I tidligere leksjoner levde og fungerte trådene våre atskilt fra hverandre. En utførte en beregning, en andre sov, og en tredje viste noe på konsollen, men de samhandlet ikke. I ekte programmer er slike situasjoner sjeldne. Flere tråder kan aktivt arbeide med og endre det samme datasettet. Dette skaper problemer. Se for deg at flere tråder skriver tekst til samme sted, for eksempel til en tekstfil eller konsollen. I dette tilfellet blir filen eller konsollen en delt ressurs. Trådene er uvitende om hverandres eksistens, så de skriver rett og slett alt de kan på den tiden de er tildelt av trådplanleggeren. I en nylig leksjon så vi et eksempel på hvor dette fører. La oss huske det nå: Trådsynkronisering.  Den synkroniserte operatøren - 2Årsaken ligger i det faktum at trådene jobber med en delt ressurs (konsollen) uten å koordinere handlingene sine med hverandre. Hvis trådplanleggeren tildeler tid til Thread-1, skriver den umiddelbart alt til konsollen. Hva andre tråder har eller ikke allerede har klart å skrive spiller ingen rolle. Resultatet, som du kan se, er deprimerende. Det er derfor de introduserte et spesielt konsept, mutex (gjensidig ekskludering) , for flertrådsprogrammering. Hensikten med en mutexer å gi en mekanisme slik at bare én tråd har tilgang til et objekt på et bestemt tidspunkt. Hvis Thread-1 henter objekt A sin mutex, vil ikke de andre trådene kunne få tilgang til og endre objektet. De andre trådene må vente til objekt A's mutex slippes. Her er et eksempel fra livet: forestill deg at du og 10 andre fremmede deltar i en øvelse. Etter tur må du uttrykke ideene dine og diskutere noe. Men fordi dere ser hverandre for første gang, for å ikke konstant avbryte hverandre og bli rasende, bruker dere en "snakkerball": bare personen med ballen kan snakke. Slik ender du opp med å få en god og fruktbar diskusjon. I hovedsak er ballen en mutex. Hvis et objekts mutex er i hendene på én tråd, kan ikke andre tråder fungere med objektet.Objectklasse, som betyr at hvert objekt i Java har en.

Hvordan den synkroniserte operatøren fungerer

La oss bli kjent med et nytt søkeord: synkronisert . Den brukes til å merke en bestemt kodeblokk. Hvis en kodeblokk er merket med nøkkelordet synchronized, kan den blokken bare kjøres av én tråd om gangen. Synkronisering kan implementeres på forskjellige måter. For eksempel, ved å erklære at en hel metode skal synkroniseres:

public synchronized void doSomething() {

   // ...Method logic
}
Eller skriv en kodeblokk der synkronisering utføres ved hjelp av et objekt:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
Meningen er enkel. Hvis en tråd går inn i kodeblokken merket med nøkkelordet synchronized, fanger den øyeblikkelig objektets mutex, og alle andre tråder som prøver å gå inn i samme blokk eller metode, blir tvunget til å vente til den forrige tråden fullfører arbeidet og slipper skjermen. Trådsynkronisering.  Den synkroniserte operatøren - 3Forresten! I løpet av kurset har du allerede sett eksempler på synchronized, men de så annerledes ut:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Emnet er nytt for deg. Og selvfølgelig vil det være forvirring med syntaksen. Så husk det med en gang for å unngå å bli forvirret senere av de forskjellige måtene å skrive det på. Disse to måtene å skrive det på betyr det samme:

public void swap() {

   synchronized (this)
   {
       // ...Method logic
   }
}


public synchronized void swap() {

   }
}
I det første tilfellet oppretter du en synkronisert kodeblokk umiddelbart etter at du går inn i metoden. Den synkroniseres av objektet this, dvs. det gjeldende objektet. Og i det andre eksemplet bruker du nøkkelordet synchronizedpå hele metoden. Dette gjør det unødvendig å eksplisitt angi objektet som brukes til synkronisering. Siden hele metoden er merket med nøkkelordet, vil metoden automatisk bli synkronisert for alle forekomster av klassen. Vi vil ikke dykke inn i en diskusjon om hvilken vei som er bedre. For nå, velg den måten du liker best :) Det viktigste er å huske: du kan erklære en metode synkronisert bare når all logikken utføres av en tråd om gangen. For eksempel ville det være en feil å gjøre følgende doSomething()metode synkronisert:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
Som du kan se, inneholder en del av metoden logikk som ikke krever synkronisering. Den koden kan kjøres av flere tråder samtidig, og alle kritiske steder er satt fra hverandre i en egen synchronizedblokk. Og en ting til. La oss se nærmere på eksempelet vårt fra leksjonen med navnebytte:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Merk: synkronisering utføres medthis. Det vil si å bruke et spesifiktMyClassobjekt. Anta at vi har 2 tråder (Thread-1ogThread-2) og bare ettMyClass myClassobjekt. I dette tilfellet, hvisThread-1kallesmyClass.swap(), vil objektets mutex være opptatt, og når du forsøker å kalle metodenmyClass.swap()vilThread-2den henge mens du venter på at mutexen skal slippes. Hvis vi skal ha 2 tråder og 2MyClassobjekter (myClass1ogmyClass2), kan trådene våre enkelt utføre de synkroniserte metodene på forskjellige objekter samtidig. Den første tråden utfører dette:

myClass1.swap();
Den andre utfører dette:

myClass2.swap();
I dette tilfellet vil ikke synchronizednøkkelordet i swap()metoden påvirke driften av programmet, siden synkronisering utføres ved hjelp av et spesifikt objekt. Og i sistnevnte tilfelle har vi 2 objekter. Dermed skaper ikke trådene problemer for hverandre. Tross alt har to objekter 2 forskjellige mutexes, og å anskaffe den ene er uavhengig av å anskaffe den andre .

Spesielle funksjoner for synkronisering i statiske metoder

Men hva om du trenger å synkronisere en statisk metode ?

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
Det er ikke klart hvilken rolle mutexen vil spille her. Tross alt har vi allerede bestemt at hvert objekt har en mutex. Men problemet er at vi ikke trenger objekter for å kalle metoden MyClass.swap(): metoden er statisk! Så hva er neste? :/ Det er faktisk ikke noe problem her. Javas skapere tok seg av alt :) Hvis en metode som inneholder kritisk samtidig logikk er statisk, utføres synkronisering på klassenivå. For større klarhet kan vi skrive om koden ovenfor som følger:

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
I prinsippet kunne du ha tenkt på dette selv: Fordi det ikke er noen objekter, må synkroniseringsmekanismen på en eller annen måte bakes inn i selve klassen. Og sånn er det: vi kan bruke klasser til å synkronisere.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION