Monitori - ohjelmointikielissä korkean tason mekanismi vuorovaikutukseen ja prosessien synkronointiin, joka tarjoaa pääsyn jaettuihin resursseihin. [1] Lähestymistapa kahden tai useamman tietokonetehtävän synkronointiin käyttämällä yhteistä resurssia, yleensä laitteistoa tai muuttujajoukkoa .
Monitoripohjaisessa moniajossa kääntäjä tai tulkki lisää läpinäkyvästi lukitus-avaa koodin asianmukaisesti muotoiltuihin rutiineihin, läpinäkyvästi ohjelmoijalle, mikä säästää ohjelmoijaa kutsumasta erikseen synkronointiprimitiivejä.
Per Brinch Hansen oli ensimmäinen, joka kuvaili ja toteutti monitorit Hoaren ideoiden pohjalta . Myöhemmin Hoare kehitti teoreettisen viitekehyksen ja osoitti sen vastaavuuden semaforeihin (käyttämällä alkuperäistä semantiikkaa). Sisältyi ensin Concurrent Pascal -kieleen ja sitä käytettiin prosessien välisen viestinnän jäsentämiseen Solo -käyttöjärjestelmässä .
Monitori koostuu:
Valvontamenettely hankkii mutexin ennen työn aloittamista ja pitää sen joko kunnes toimenpide päättyy tai kunnes ehtoa odotetaan (katso alla). Jos jokainen toimenpide takaa, että invariantti on tosi ennen mutexin vapauttamista, mikään tehtävä ei voi hankkia resurssia kilpailutilassa.
Yksinkertainen esimerkki. Harkitse monitoria, joka suorittaa pankkitilitapahtumia.
valvoa tiliä { int saldo := 0 toiminto nosta( int summa) { if summa < 0 then error "Tili ei voi olla negatiivinen" else if saldo < summa sitten virhe "Varojen puute" else saldo := saldo - summa } funktio talletus( int summa) { if summa < 0 then error "Summa ei voi olla negatiivinen" muuten saldo := saldo + summa } }Tässä oleva invariantti sanoo yksinkertaisesti, että saldon on heijastettava kaikkia aiempia tapahtumia ennen uuden tapahtuman alkamista. Tätä ei yleensä ilmaista koodissa, vaan se on implisiittistä ja voidaan mainita kommenteissa . On kuitenkin olemassa ohjelmointikieliä, kuten Eiffel tai D , jotka voivat tarkistaa invarianttien varalta. Kääntäjä lisää lukon. Tämä tekee näytöistä turvallisempia ja kätevämpiä kuin muut lähestymistavat, jotka edellyttävät ohjelmoijaa lisäämään lukitus-avaa toiminnot manuaalisesti, koska ohjelmoija saattaa unohtaa lisätä ne.
Aktiivisen odotustilan välttämiseksi prosessien on viestittävä toisilleen odotetuista tapahtumista. Monitorit tarjoavat tämän ominaisuuden ehtomuuttujien kautta . Kun valvontamenettely edellyttää tietyn ehdon täyttymistä voidakseen jatkaa, se odottaa siihen liittyvää ehtomuuttujaa. Odottaessaan se vapauttaa väliaikaisesti mutexin ja putoaa käynnissä olevien prosessien luettelosta. Mikä tahansa prosessi, joka myöhemmin aiheuttaa tämän ehdon täyttymisen, käyttää ehtomuuttujaa ilmoittamaan odotusprosessista. Ilmoitettu prosessi hankkii uudelleen mutexin ja voi jatkua.
Seuraava monitori käyttää ehtomuuttujia toteuttamaan prosessien välistä kanavaa, joka voi tallentaa vain yhden kokonaisluvun kerrallaan.
valvontakanava { int sisältö boolean full := false condition snd condition rcv function send( int message) { while full do wait(rcv) // Mesa semantiikka: katso alla sisältö := viesti täynnä := totta ilmoittaa (snd) } function Receive() { var int vastaanotettu while not full do wait(snd) // Mesa semantiikka: katso alla vastaanotettu := sisältö täynnä := false ilmoittaa (rcv) palautus saatu } }Huomaa, että koska ehdon odottaminen vapauttaa lukon, odotusprosessin on varmistettava, että invariantti täyttyy ennen odottamisen aloittamista. Yllä olevassa esimerkissä sama pätee varoitukseen.
Varhaisissa monitorointitoteutuksissa (tunnetaan nimellä Hoare -semantiikka ) ehtomuuttujan ilmoittaminen herättää välittömästi odotusprosessin ja palauttaa lukon, mikä varmistaa, että ehto on edelleen tosi.
Tämän käyttäytymisen toteuttaminen on monimutkaista ja erittäin tarpeetonta. Se ei myöskään ole yhteensopiva ennaltaehkäisevän multitaskingin kanssa , jossa prosessi voidaan keskeyttää mielivaltaisella hetkellä. Näistä syistä tutkijat ovat kehittäneet monia muita semantiikkaa ehtomuuttujille.
Uusimmissa toteutuksissa (tunnetaan nimellä Mesa semantics ) ilmoitus ei keskeytä käynnissä olevaa prosessia, vaan yksinkertaisesti laittaa jotkin odottavat prosessit valmiustilaan. Ilmoitusprosessi jatkaa lukkoa, kunnes se poistuu valvontamenettelystä. Tämän lähestymistavan sivuvaikutuksia ovat, että ilmoitusprosessin ei edellytetä tarkkailevan ilmoitusta edeltävää invarianttia, vaan odotusprosessin on tarkistettava uudelleen ehto, jota se odottaa. Erityisesti, jos valvontaproseduuri sisältää lausekkeen , toinen prosessi voi tulla monitoriin ilmoitushetken jälkeen ja muuttaa arvoa ennen kuin odotusprosessi jatkuu. Lauseke tulee kirjoittaa uudelleen seuraavasti: niin , että ehto tarkistetaan uudelleen odotuksen jälkeen. if test then wait(cv)testwhile test do wait(cv)
Toteutukset tarjoavat myös "notifyAll"- tai "broadcast"-toiminnon, joka ilmoittaa kaikille tiettyä ehtoa odottaville prosesseille. Tämä toiminto on hyödyllinen esimerkiksi silloin, kun useat prosessit odottavat eri määrien muistia olevan käytettävissä. Muistin vapauttaminen antaa yhden niistä jatkaa toimintaansa, mutta ajastaja ei voi tietää, mikä.
Esimerkki ehtomuuttujan toteutuksesta:
ehtomuuttuja { int queueSize = 0; mutex lukko; semafori odottaa; odota() { lock.acquire(); queueSize++; lock.release(); odottaa.alas(); } signaali() { lock.acquire(); while (queueSize > 0){ queueSize--; odottaa.up(); } lock.release(); } }Monitoreja tukevat ohjelmointikielet: