CodeGym /Java-blogg /Tilfeldig /Forskjellen mellom en Mutex, en monitor og en semafor
John Squirrels
Nivå
San Francisco

Forskjellen mellom en Mutex, en monitor og en semafor

Publisert i gruppen
Hei! Når du studerte multithreading på CodeGym, møtte du ofte begrepene "mutex" og "monitor". Uten å kikke, kan du si hvordan de er forskjellige? :) Hvis ja, godt gjort! Hvis ikke (dette er mest vanlig), er det ingen overraskelse. "Mutex" og "monitor" er faktisk relaterte begreper. I tillegg, når du leser leksjoner og ser videoer om multithreading på andre nettsteder, vil du komme over et annet lignende konsept: "semafor". Den har også en veldig lik funksjon som monitorer og mutexes. Det er derfor vi skal undersøke disse tre begrepene. Vi skal se på noen få eksempler og komme til en endelig forståelse av hvordan disse konseptene skiller seg fra hverandre :)

Mutex

En mutex (eller lås) er en spesiell mekanisme for synkronisering av tråder. En er "festet" til hvert objekt i Java — det vet du allerede :) Det spiller ingen rolle om du bruker standardklasser eller lager dine egne klasser, f.eks. Cat and Dog : alle objekter i alle klasser har en mutex . Begrepet "mutex" kommer fra "MUTual EXclusion", som perfekt beskriver formålet. Som vi sa i en av våre tidligere leksjoner, gjør en mutex det mulig å sikre at kun én tråd om gangen har tilgang til objektet. Et populært eksempel fra virkeligheten på en mutex involverer toaletter. Når en person går inn i en toalettskillevegg, låser han døren fra innsiden. Toalettet er som en gjenstand som kan nås med flere tråder. Låsen på skilleveggen er som en mutex, og rekken av mennesker utenfor representerer tråder. Låsen på døren er toalettets mutex: den sikrer at bare én person kan komme inn. Hva er forskjellen mellom en mutex, en monitor og en semafor?  - 2Med andre ord, bare én tråd om gangen kan jobbe med delte ressurser. Forsøk fra andre tråder (personer) for å få tilgang til okkuperte ressurser vil mislykkes. En mutex har flere viktige funksjoner. For det første er bare to tilstander mulig: "ulåst" og "låst". Dette hjelper oss å forstå hvordan det fungerer: du kan trekke paralleller med boolske variabler (sant/usant) eller binære tall (0/1). , staten kan ikke kontrolleres direkte. Java har ingen mekanisme som lar deg eksplisitt ta et objekt, få mutex, og tildele ønsket status. Du kan med andre ord ikke gjøre noe som:

Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Dette betyr at du ikke kan frigjøre et objekts mutex. Bare Java-maskinen har direkte tilgang til den. Programmerere jobber med mutexes gjennom verktøyene til språket.

Observere

En monitor er en ekstra "overbygning" over en mutex. Faktisk er en skjerm en kodebit som er "usynlig" for programmereren. Da vi snakket om mutexes tidligere, ga vi et enkelt eksempel:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
I kodeblokken merket med det synkroniserte nøkkelordet, blir mutexen til objektet vårt hentet inn. Flott, vi kan anskaffe låsen, men hvordan gis nøyaktig "beskyttelsen"? Når vi ser ordet synkronisert , hva hindrer de andre trådene i å gå inn i blokken? Beskyttelsen kommer fra en skjerm! Kompilatoren konverterer det synkroniserte nøkkelordet til flere spesielle kodebiter. Nok en gang, la oss gå tilbake til vårt eksempel med doSomething() -metoden. Vi legger til det:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time
       synchronized (obj) {

           /* Do important work that requires that the object
           be accessed by only one thread */
           obj.someImportantMethod();
       }
   }
}
Her er hva som skjer "under panseret" etter at kompilatoren konverterer denne koden:

public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time:
     
       /* as long as the object's mutex is busy,
       all the other threads (except the one that acquired it) are put to sleep */
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       // Mark the object's mutex as busy
       obj.getMutex().isBusy() = true;

       /* Do important work that requires that the object
       be accessed by only one thread */
       obj.someImportantMethod();

       // Free the object's mutex
       obj.getMutex().isBusy() = false;
   }
}
Dette er selvfølgelig ikke et ekte eksempel. Her brukte vi Java-lignende kode for å skildre hva som skjer inne i Java-maskinen. Når det er sagt, gir denne pseudokoden en utmerket forståelse av hva som faktisk skjer med objektet og trådene inne i den synkroniserte blokken og hvordan kompilatoren konverterer dette nøkkelordet til flere utsagn som er "usynlige" for programmereren. I utgangspunktet bruker Java det synkroniserte nøkkelordet for å representere en skjerm . All koden som vises i stedet for det synkroniserte nøkkelordet i det siste eksemplet er skjermen.

Semafor

Et annet ord du vil møte i din personlige studie av multithreading er "semafor". La oss finne ut hva dette er og hvordan det skiller seg fra en skjerm og en mutex. En semafor er et verktøy for å synkronisere tilgang til en ressurs. Dens karakteristiske trekk er at den bruker en teller for å lage synkroniseringsmekanismen. Telleren forteller oss hvor mange tråder som kan få tilgang til den delte ressursen samtidig. Hva er forskjellen mellom en mutex, en monitor og en semafor?  - 3Semaforer i Java er representert av Semaphore -klassen. Når vi lager semaforobjekter, kan vi bruke følgende konstruktører:

Semaphore(int permits)
Semaphore(int permits, boolean fair)
Vi sender følgende til konstruktøren:
    int permits — start- og maksimumsverdien til telleren. Med andre ord, denne parameteren bestemmer hvor mange tråder som kan få tilgang til den delte ressursen samtidig;
  • boolean fair — etablerer rekkefølgen som tråder vil få tilgang til. Hvis rettferdig er sant, gis tilgang til ventende tråder i den rekkefølgen de ba om det. Hvis det er usant, bestemmes rekkefølgen av trådplanleggeren.
Et klassisk eksempel på semaforbruk er spisefilosofproblemet. Hva er forskjellen mellom en mutex, en monitor og en semafor?  - 4For å lette forståelsen, vil vi forenkle det litt. Tenk deg at vi har 5 filosofer som trenger å spise lunsj. I tillegg har vi ett bord som ikke kan romme mer enn to personer samtidig. Vår oppgave er å mate alle filosofene. Ingen av dem skal gå sultne, og ingen av dem skal "blokkere" hverandre når de prøver å sette seg til bords (vi må unngå vranglås). Slik vil filosofklassen vår se ut:

class Philosopher extends Thread {

   private Semaphore sem;

   // Did the philosopher eat?
   private boolean full = false;

   private String name;

   Philosopher(Semaphore sem, String name) {
       this.sem=sem;
       this.name=name;
   }

   public void run()
   {
       try
       {
           // If the philosopher has not eaten
           if (!full) {
               // Ask the semaphore for permission to run
               sem.acquire();
               System.out.println(name + " takes a seat at the table");

               // The philosopher eats
               sleep(300);
               full = true;

               System.out.println(name + " has eaten! He leaves the table");
               sem.release();

               // The philosopher leaves, making room for others
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println("Something went wrong!");
       }
   }
}
Og her er koden for å kjøre programmet vårt:

public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem, "Socrates").start();
       new Philosopher(sem,"Plato").start();
       new Philosopher(sem,"Aristotle").start();
       new Philosopher(sem, "Thales").start();
       new Philosopher(sem, "Pythagoras").start();
   }
}
Vi laget en semafor hvis teller er satt til 2 for å tilfredsstille betingelsen: bare to filosofer kan spise samtidig. Det vil si at bare to tråder kan kjøres samtidig, fordi Philosopher -klassen vår arver Thread ! Acquisition () og release()- metodene til Semaphore -klassen kontrollerer tilgangstelleren. Acquisit()-metoden ber semaforen om tilgang til ressursen. Hvis telleren er >0, gis tilgang og telleren reduseres med 1. Utgivelsen ()metoden "frigir" den tidligere gitte tilgangen, og returnerer den til telleren (øker semaforens tilgangsteller med 1). Hva får vi når vi kjører programmet? Er problemet løst? Vil ikke våre filosofer kjempe mens de venter på tur? :) Her er konsollutgangen vi fikk:

Socrates takes a seat at the table 
Plato takes a seat at the table 
Socrates has eaten! He leaves the table 
Plato has eaten! He leaves the table 
Aristotle takes a seat at the table 
Pythagoras takes a seat at the table 
Aristotle has eaten! He leaves the table 
Pythagoras has eaten! He leaves the table 
Thales takes a seat at the table 
Thales has eaten! He leaves the table 
Vi gjorde det! Og selv om Thales måtte spise alene, tror jeg ikke vi har fornærmet ham :) Du har kanskje lagt merke til noen likheter mellom en mutex og en semafor. Faktisk har de samme oppdrag: å synkronisere tilgang til en eller annen ressurs. Hva er forskjellen mellom en mutex, en monitor og en semafor?  - 5Den eneste forskjellen er at et objekts mutex kan innhentes av bare én tråd om gangen, mens i tilfellet med en semafor, som bruker en trådteller, kan flere tråder få tilgang til ressursen samtidig. Dette er ikke bare en tilfeldighet :) En mutex er faktisk en semaformed en telling på 1. Det er med andre ord en semafor som kan romme en enkelt tråd. Det er også kjent som en "binær semafor" fordi telleren kan ha bare 2 verdier - 1 ("ulåst") og 0 ("låst"). Det er det! Som du kan se, er det ikke så forvirrende likevel :) Hvis du nå vil studere multithreading mer detaljert på Internett, vil det være litt lettere for deg å navigere i disse konseptene. Vi sees i neste leksjoner!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION