JavaRush /Java Blog /Random-TL /Ano ang pagkakaiba sa pagitan ng isang mutex, isang monit...

Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore

Nai-publish sa grupo
Kamusta! Habang nag-aaral ng multithreading sa JavaRush, madalas mong makita ang mga konsepto ng "mutex" at "monitor". Maaari mo ba ngayon, nang hindi sumilip, sagutin kung paano sila naiiba? :) Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore - 1Kung kaya mo, magaling! Kung hindi (at kadalasan nangyayari ito) - hindi nakakagulat. Ang mga konsepto ng "mutex" at "monitor" ay talagang magkakaugnay. Bukod dito, habang nagbabasa ng mga lektura at nanonood ng mga video sa multithreading sa mga panlabas na mapagkukunan sa Internet, makakatagpo ka ng isa pang katulad na konsepto - "semaphore". Ang pag-andar nito ay halos katulad din sa isang monitor at isang mutex. Samakatuwid, unawain natin ang tatlong terminong ito, tingnan ang ilang mga halimbawa at sa wakas ay ayusin sa ating mga ulo ang pag-unawa kung paano sila naiiba sa bawat isa :)

Mutex

Ang mutex ay isang espesyal na bagay para sa pag-synchronize ng mga thread. Ito ay "naka-attach" sa bawat bagay sa Java - alam mo na iyon :) Hindi mahalaga kung gumagamit ka ng mga karaniwang klase o lumikha ng iyong sariling mga klase, sabihin, Catat Dog: lahat ng mga bagay sa lahat ng mga klase ay may mutex . Ang pangalang "mutex" ay nagmula sa English na "MUTual Exclusion" - "mutual exclusion", at ito ay perpektong sumasalamin sa layunin nito. Gaya ng sinabi namin sa isa sa mga nakaraang lecture, ang gawain ng isang mutex ay magbigay ng ganoong mekanismo upang ang isang thread lamang ang may access sa isang bagay sa isang tiyak na oras . Ang isang popular na pagkakatulad para sa isang mutex sa totoong buhay ay ang "halimbawa sa banyo." Kapag ang isang tao ay pumasok sa banyo, ini-lock niya ang pinto mula sa loob. Ang banyo ay gumaganap bilang isang bagay na maaaring ma-access ng maraming mga thread. Ang lock sa pinto ng banyo ay ang papel ng isang mutex, at ang pila ng mga tao sa labas ay ang papel ng mga thread. Ang lock sa pinto ay isang toilet mutex: tinitiyak nito na isang tao lang ang maaaring makapasok sa loob sa isang pagkakataon. Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore - 2Sa madaling salita, isang thread lang sa isang pagkakataon ang maaaring gumana sa mga nakabahaging mapagkukunan. Mabibigo ang mga pagtatangka ng iba pang mga thread (mga tao) na i-access ang mga okupado na mapagkukunan. Ang isang mutex ay may ilang mahahalagang katangian. Una , dalawang estado lamang ang posible - "libre" at "abala". Ginagawa nitong mas madaling maunawaan kung paano ito gumagana: maaaring iguhit ang mga parallel gamit ang mga variable ng Boolean na true/false o ang binary number system na 1/0. Pangalawa , ang mga estado ay hindi maaaring direktang kontrolin. Walang mga mekanismo sa Java na magpapahintulot sa iyo na tahasang kumuha ng isang bagay, kunin ang mutex nito at italaga ang nais na katayuan dito. Sa madaling salita, hindi mo magagawa ang isang bagay tulad ng:
Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Kaya, ang mutex ng bagay ay hindi maaaring ilabas. Tanging ang Java machine lamang ang may direktang access dito. Nagtatrabaho ang mga programmer sa mga mutex gamit ang mga tool sa wika.

Subaybayan

Ang monitor ay isang karagdagang "add-on" sa isang mutex. Sa katunayan, ang monitor ay isang piraso ng code na "hindi nakikita" ng programmer . Sa pagsasalita tungkol sa mutex kanina, nagbigay kami ng isang simpleng halimbawa:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
Sa bloke ng code na minarkahan ng salita synchronized, ang mutex ng aming bagay ay nakunan obj. Okay, nangyayari ang pagkuha, ngunit paano nga ba nakakamit ang "mekanismo ng pagtatanggol"? synchronizedBakit hindi makapasok ang ibang mga thread sa loob ng block kapag nakakita sila ng isang salita ? Ito ay ang monitor na lumilikha ng proteksiyon na mekanismo! Kino-convert ng compiler ang salita synchronizedsa ilang espesyal na piraso ng code. Muli, bumalik tayo sa ating halimbawa kasama ang pamamaraan doSomething()at idagdag dito:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       //logic that is only available to one thread at a time
       synchronized (obj) {

           /*выполнить важную работу, при которой доступ к an objectу
           должен быть только у одного потока*/
           obj.someImportantMethod();
       }
   }
}
Narito kung ano ang mangyayari "sa ilalim ng hood" ng aming programa pagkatapos na i-convert ng compiler ang code na ito:
public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       //...some logic available to all threads

       //логика, которая одновременно доступна только для одного потока:

       /*до тех пор, пока мьютекс an object занят -
       любой другой поток (кроме того, который его захватил), спит*/
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       //пометить мьютекс an object How занятый
       obj.getMutex().isBusy() = true;

       /*выполнить важную работу, при которой доступ к an objectу
       должен быть только у одного потока*/
       obj.someImportantMethod();

       //освободить мьютекс an object
       obj.getMutex().isBusy() = false;
   }
}
Ang halimbawa ay, siyempre, hindi totoo. Dito, gamit ang Java-like code, sinubukan naming ipakita kung ano ang nangyayari sa sandaling ito sa loob ng Java machine. Gayunpaman, ang pseudocode na ito ay nagbibigay ng isang mahusay na pag-unawa sa kung ano ang aktwal na nangyayari sa object at mga thread sa loob ng block synchronizedat kung paano kino-convert ng compiler ang salitang ito sa ilang mga command na "invisible" ng programmer. Mahalaga, ang monitor sa Java ay ipinahayag gamit ang salitangsynchronized . Ang lahat ng code na lumitaw sa halip na ang salita synchronizedsa huling halimbawa ay ang monitor.

Semaphore

Ang isa pang salita na makikita mo kapag nag-aaral ng multithreading sa iyong sarili ay "semaphore". Alamin natin kung ano ito at kung paano ito naiiba sa isang monitor at isang mutex. Ang semaphore ay isang paraan para sa pag-synchronize ng access sa isang mapagkukunan. Ang kakaiba nito ay gumagamit ito ng counter kapag lumilikha ng mekanismo ng pag-synchronize. Sinasabi sa amin ng counter kung gaano karaming mga thread ang maaaring sabay na ma-access ang isang nakabahaging mapagkukunan. Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore - 3Ang mga semaphore sa Java ay kinakatawan ng klase Semaphore. Kapag lumilikha ng mga bagay na semaphore, maaari naming gamitin ang mga sumusunod na konstruktor:
Semaphore(int permits)
Semaphore(int permits, boolean fair)
Dumaan kami sa tagabuo:
  • int permits— paunang at pinakamataas na halaga ng counter. Iyon ay, kung gaano karaming mga thread ang maaaring sabay na ma-access ang isang nakabahaging mapagkukunan;

  • boolean fair- upang itatag ang pagkakasunud-sunod kung saan ang mga thread ay makakatanggap ng access. Kung fair= true , ibinibigay ang access sa naghihintay na mga thread sa pagkakasunud-sunod kung saan nila ito hiniling. Kung ito ay mali , ang pagkakasunud-sunod ay tutukuyin ng thread scheduler.

Ang isang klasikong halimbawa ng paggamit ng mga semaphore ay ang problema ng mga pilosopo sa pananghalian .
Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore - 4
Pasimplehin natin nang kaunti ang mga termino nito para sa mas mahusay na pag-unawa. Isipin na mayroon kaming 5 pilosopo na nangangailangan ng tanghalian. Sa parehong oras, mayroon kaming isang mesa, at hindi hihigit sa dalawang tao ang maaaring magkasama dito. Ang aming gawain ay pakainin ang lahat ng mga pilosopo. Wala sa kanila ang dapat magutom, o dapat silang "magharang" sa isa't isa kapag sinusubukang umupo sa mesa (kailangan nating iwasan ang deadlock). Ito ang magiging hitsura ng aming klase ng pilosopo:
class Philosopher extends Thread {

   private Semaphore sem;

   // поел ли философ
   private boolean full = false;

   private String name;

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

   public void run()
   {
       try
       {
           // если философ еще не ел
           if (!full) {
               //Запрашиваем у семафора разрешение на выполнение
               sem.acquire();
               System.out.println (name + " садится за стол");

               // философ ест
               sleep(300);
               full = true;

               System.out.println (name + " поел! Он выходит из-за стола");
               sem.release();

               // философ ушел, освободив место другим
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println ("What-то пошло не так!");
       }
   }
}
At narito ang code upang patakbuhin ang aming programa:
public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem,"Сократ").start();
       new Philosopher(sem,"Платон").start();
       new Philosopher(sem,"Аристотель").start();
       new Philosopher(sem,"Фалес").start();
       new Philosopher(sem,"Пифагор").start();
   }
}
Gumawa kami ng isang semaphore na may bilang na 2 upang matugunan ang kondisyon na dalawang pilosopo lamang ang makakain nang sabay. Iyon ay, dalawang thread lamang ang maaaring gumana nang sabay-sabay, dahil ang aming klase Philosopheray minana mula sa Thread! Kinokontrol ng klase acquire()at mga pamamaraan ang counter ng pahintulot nito. Ang pamamaraan ay humihiling ng pahintulot na ma-access ang isang mapagkukunan mula sa semaphore. Kung ang counter > 0, ang pahintulot ay ipinagkaloob at ang counter ay binabawasan ng 1. Ang pamamaraan ay "naglalabas" ng dati nang ipinagkaloob na pahintulot at ibinabalik ito sa counter (incrementing ang grant counter ng semaphore ng 1). Ano ang makukuha natin kapag pinapatakbo natin ang programa? Nalutas na ba ang problema?Maglalaban ba ang ating mga pilosopo habang naghihintay ng kanilang turn? :) Ito ang console output na natanggap namin: Umupo si Socrates sa table Umupo si Plato sa table na kinain ni Socrates! Umalis siya sa hapag. Kumain na si Plato! Iniwan niya ang mesa Umupo si Aristotle sa mesa Umupo si Pythagoras sa mesang kinain ni Aristotle! Umalis siya sa mesang kinain ni Pythagoras! Umalis siya sa mesa Umupo si Thales sa mesang kinain ni Thales! Umalis siya sa mesa. Nagtagumpay kami! At bagama't kinailangan ni Thales na kumain mag-isa, sa tingin ko hindi siya galit sa amin :) Maaaring napansin mo ang ilang pagkakatulad sa pagitan ng mutex at semaphore. Sa pangkalahatan, mayroon silang parehong layunin: upang i-synchronize ang pag-access sa ilang mapagkukunan. Ang pagkakaiba lamang ay ang mutex ng isang bagay ay maaari lamang makuha sa pamamagitan ng isang thread sa isang pagkakataon, habang sa kaso ng isang semaphore, isang thread counter ay ginagamit, at ilan sa kanila ay maaaring ma-access ang mapagkukunan nang sabay-sabay. At hindi lang ito nagkataon na pagkakatulad :) Sa katunayan, ang mutex ay isang solong lugar na semaphore . Iyon ay, ito ay isang semaphore na ang counter ay unang nakatakda sa 1. Tinatawag din itong "binary semaphore" dahil ang counter nito ay maaari lamang magkaroon ng 2 value - 1 ("libre") at 0 ("busy"). Iyon lang! Tulad ng nakikita mo, ang lahat ay naging hindi nakakalito :) Ngayon, kung gusto mong pag-aralan ang paksa ng multithreading nang mas detalyado sa Internet, magiging mas madali para sa iyo na mag-navigate sa mga konsepto. Magkita-kita tayo sa susunod na mga aralin! release()Semaphoreacquire()release()Ano ang pagkakaiba sa pagitan ng isang mutex, isang monitor at isang semaphore - 5
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION