CodeGym /Java blog /Tilfældig /Trådsynkronisering. Den synkroniserede operatør
John Squirrels
Niveau
San Francisco

Trådsynkronisering. Den synkroniserede operatør

Udgivet i gruppen
Hej! I dag vil vi fortsætte med at overveje funktionerne i multithreaded programmering og tale om trådsynkronisering. Trådsynkronisering.  Den synkroniserede operatør - 1

Hvad er synkronisering i Java?

Uden for programmeringsdomænet indebærer det et arrangement, der tillader to enheder eller programmer at arbejde sammen. For eksempel kan en smartphone og computer synkroniseres med en Google-konto, og en hjemmesidekonto kan synkroniseres med sociale netværkskonti, så du kan bruge dem til at logge ind. Trådsynkronisering har en lignende betydning: det er et arrangement, hvor tråde interagerer med hinanden. I tidligere lektioner levede og arbejdede vores tråde adskilt fra hinanden. En udførte en beregning, en anden sov, og en tredje viste noget på konsollen, men de interagerede ikke. I rigtige programmer er sådanne situationer sjældne. Flere tråde kan aktivt arbejde med og ændre det samme datasæt. Dette skaber problemer. Forestil dig, at flere tråde skriver tekst til det samme sted, for eksempel til en tekstfil eller konsollen. I dette tilfælde bliver filen eller konsollen en delt ressource. Trådene er uvidende om hinandens eksistens, så de skriver simpelthen alt, hvad de kan på den tid, som trådplanlæggeren har tildelt dem. I en nylig lektion så vi et eksempel på, hvor dette fører hen. Lad os huske det nu: Trådsynkronisering.  Den synkroniserede operatør - 2Årsagen ligger i, at trådene arbejder med en delt ressource (konsollen) uden at koordinere deres handlinger med hinanden. Hvis trådplanlæggeren tildeler tid til Thread-1, så skriver den øjeblikkeligt alt til konsollen. Hvilke andre tråde har eller ikke allerede har formået at skrive er ligegyldigt. Resultatet er, som du kan se, deprimerende. Det er derfor, de introducerede et særligt koncept, mutex (gensidig udelukkelse) , til flertrådsprogrammering. Formålet med en mutexer at tilvejebringe en mekanisme, så kun én tråd har adgang til et objekt på et bestemt tidspunkt. Hvis Tråd-1 henter objekt A's mutex, vil de andre tråde ikke være i stand til at få adgang til og ændre objektet. De andre tråde skal vente, indtil objekt A's mutex er frigivet. Her er et eksempel fra livet: Forestil dig, at du og 10 andre fremmede deltager i en øvelse. På skift skal du udtrykke dine ideer og diskutere noget. Men fordi man ser hinanden for første gang, for ikke konstant at afbryde hinanden og flyve i raseri, bruger man en 'talende bold': kun personen med bolden kan tale. På denne måde ender du med at få en god og frugtbar diskussion. Dybest set er bolden en mutex. Hvis et objekts mutex er i hænderne på én tråd, kan andre tråde ikke fungere med objektet.Objectklasse, hvilket betyder, at hvert objekt i Java har en.

Hvordan den synkroniserede operatør fungerer

Lad os lære et nyt søgeord at kende: synkroniseret . Det bruges til at markere en bestemt kodeblok. Hvis en kodeblok er markeret med nøgleordet synchronized, kan denne blok kun udføres af én tråd ad gangen. Synkronisering kan implementeres på forskellige måder. For eksempel ved at erklære en hel metode for at være synkroniseret:

public synchronized void doSomething() {

   // ...Method logic
}
Eller skriv en kodeblok, hvor synkronisering udføres ved hjælp af 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
       }
   }
}
Betydningen er enkel. Hvis en tråd går ind i kodeblokken markeret med nøgleordet synchronized, fanger den øjeblikkeligt objektets mutex, og alle andre tråde, der forsøger at indtaste den samme blok eller metode, er tvunget til at vente, indtil den forrige tråd fuldfører sit arbejde og frigiver monitoren. Trådsynkronisering.  Den synkroniserede operatør - 3I øvrigt! I løbet af kurset har du allerede set eksempler på synchronized, men de så anderledes ud:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Emnet er nyt for dig. Og selvfølgelig vil der være forvirring med syntaksen. Så husk det med det samme for at undgå at blive forvirret senere af de forskellige måder at skrive det på. Disse to måder at skrive det på betyder det samme:

public void swap() {

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


public synchronized void swap() {

   }
}
I det første tilfælde opretter du en synkroniseret kodeblok umiddelbart efter indtastning af metoden. Det synkroniseres af objektet this, altså det aktuelle objekt. Og i det andet eksempel anvender du søgeordet synchronizedpå hele metoden. Dette gør det unødvendigt eksplicit at angive det objekt, der bruges til synkronisering. Da hele metoden er markeret med nøgleordet, vil metoden automatisk blive synkroniseret for alle forekomster af klassen. Vi vil ikke dykke ned i en diskussion om, hvilken vej der er bedre. Indtil videre, vælg den måde, du bedst kan lide :) Det vigtigste er at huske: du kan kun erklære en metode synkroniseret, når hele dens logik udføres af en tråd ad gangen. For eksempel ville det være en fejl at gøre følgende doSomething()metode synkroniseret:

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, indeholder en del af metoden logik, der ikke kræver synkronisering. Denne kode kan køres af flere tråde på samme tid, og alle kritiske steder er adskilt i en separat synchronizedblok. Og en ting mere. Lad os nøje undersøge vores eksempel fra lektionen med navnebytte:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Bemærk: synkronisering udføres ved hjælp afthis. Det vil sige at bruge et bestemtMyClassobjekt. Antag, at vi har 2 tråde (Thread-1ogThread-2) og kun etMyClass myClassobjekt. I dette tilfælde, hvisThread-1kaldesmyClass.swap(), vil objektets mutex være optaget, og når man forsøger at kaldemyClass.swap()metodenThread-2, hænger den, mens man venter på, at mutex'et bliver frigivet. Hvis vi vil have 2 tråde og 2MyClassobjekter (myClass1ogmyClass2), kan vores tråde nemt udføre de synkroniserede metoder på forskellige objekter samtidigt. Den første tråd udfører dette:

myClass1.swap();
Den anden udfører dette:

myClass2.swap();
I dette tilfælde vil synchronizednøgleordet i swap()metoden ikke påvirke driften af ​​programmet, da synkronisering udføres ved hjælp af et bestemt objekt. Og i sidstnævnte tilfælde har vi 2 objekter. Trådene skaber således ikke problemer for hinanden. To objekter har jo 2 forskellige mutexes, og at erhverve den ene er uafhængig af at erhverve den anden .

Særlige træk ved synkronisering i statiske metoder

Men hvad hvis du har brug for at 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 mutex'en vil spille her. Vi har jo allerede bestemt, at hvert objekt har en mutex. Men problemet er, at vi ikke behøver objekter for at kalde metoden MyClass.swap(): metoden er statisk! Så hvad er det næste? :/ Der er faktisk ikke noget problem her. Javas skabere tog sig af alt :) Hvis en metode, der indeholder kritisk samtidig logik, er statisk, så udføres synkronisering på klasseniveau. For større klarhed kan vi omskrive ovenstående kode 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 princippet kunne du selv have tænkt på dette: Fordi der ikke er nogen objekter, skal synkroniseringsmekanismen på en eller anden måde bages ind i selve klassen. Og sådan er det: Vi kan bruge klasser til at synkronisere.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION