CodeGym/Curs Java/Modulul 3/Modele cu mai multe fire

Modele cu mai multe fire

Disponibil

3.1 Obiect activ

Un obiect activ este un model de proiectare care separă firul de execuție al unei metode de firul în care a fost chemat. Scopul acestui model este de a oferi execuție paralelă folosind apeluri de metodă asincrone și un planificator de procesare a cererilor.

Versiune simplificata:

obiect activ

Varianta clasica:

Obiect activ 2

Acest șablon are șase elemente:

  • Un obiect proxy care oferă o interfață cu metodele publice ale clientului.
  • O interfață care definește metode de acces pentru obiectul activ.
  • Lista cererilor primite de la clienți.
  • Un planificator care determină ordinea în care urmează să fie executate interogările.
  • Implementarea metodelor obiectului activ.
  • O procedură de apel invers sau o variabilă pentru ca clientul să primească un rezultat.

3.2 blocare

Modelul de blocare este un mecanism de sincronizare care permite accesul exclusiv la o resursă partajată între mai multe fire. Blocările sunt o modalitate de a aplica politica de control al concurenței.

Practic, se folosește o blocare soft, cu presupunerea că fiecare fir încearcă să „obțină blocarea” înainte de a accesa resursa partajată corespunzătoare.

Cu toate acestea, unele sisteme oferă un mecanism de blocare obligatoriu prin care o încercare de acces neautorizat la o resursă blocată va fi anulată prin lansarea unei excepții pe firul de execuție care a încercat să obțină acces.

Un semafor este cel mai simplu tip de blocare. În ceea ce privește accesul la date, nu se face distincție între modurile de acces: partajat (numai citire) sau exclusiv (citire-scriere). În modul partajat, mai multe fire de execuție pot solicita o blocare pentru a accesa datele în modul numai citire. Modul de acces exclusiv este folosit și în algoritmii de actualizare și ștergere.

model de blocare

Tipurile de încuietori se disting prin strategia de blocare a continuării execuției firului. În majoritatea implementărilor, o solicitare pentru o blocare împiedică firul de execuție să continue să se execute până când resursa blocată este disponibilă.

Un spinlock este o blocare care așteaptă într-o buclă până când accesul este acordat. O astfel de blocare este foarte eficientă dacă un thread așteaptă o blocare pentru o perioadă mică de timp, evitând astfel reprogramarea excesivă a firelor. Costul așteptării accesului va fi semnificativ dacă unul dintre fire ține blocarea mult timp.

model de blocare 2

Pentru a implementa eficient mecanismul de blocare, este necesar suport la nivel hardware. Suportul hardware poate fi implementat ca una sau mai multe operațiuni atomice, cum ar fi „test-and-set”, „fetch-and-add” sau „compare-and-swap”. Astfel de instrucțiuni vă permit să verificați fără întrerupere dacă blocarea este liberă și, dacă da, atunci obțineți blocarea.

3.3 Monitor

Modelul Monitor este un mecanism de interacțiune și sincronizare cu proces la nivel înalt care oferă acces la resursele partajate. O abordare a sincronizării a două sau mai multe sarcini de calculator folosind o resursă comună, de obicei hardware sau un set de variabile.

În multitasking bazat pe monitor, compilatorul sau interpretul inserează în mod transparent codul de blocare-deblocare în rutine formatate corespunzător, în mod transparent pentru programator, salvând programatorul de la apelarea explicită a primitivelor de sincronizare.

Monitorul este format din:

  • un set de proceduri care interacționează cu o resursă partajată
  • mutex
  • variabile asociate acestei resurse
  • un invariant care definește condiții pentru a evita o condiție de rasă

Procedura de monitorizare dobândește mutexul înainte de a începe lucrul și îl menține fie până la ieșirea procedurii, fie până când se așteaptă o anumită condiție. Dacă fiecare procedură garantează că invariantul este adevărat înainte de a elibera mutex-ul, atunci nicio sarcină nu poate achiziționa resursa într-o condiție de cursă.

Așa lucrează operatorul sincronizat în Java cu metodele wait()și notify().

3.4 Verificați dublu blocare

Blocarea dublu verificată este un model de proiectare paralel menit să reducă cheltuielile generale pentru obținerea unei încuietori.

În primul rând, starea de blocare este verificată fără nicio sincronizare. Un fir încearcă să obțină o blocare numai dacă rezultatul verificării indică faptul că trebuie să obțină blocarea.

//Double-Checked Locking
public final class Singleton {
private static Singleton instance; //Don't forget volatile modifier

public static Singleton getInstance() {
     if (instance == null) {                //Read

         synchronized (Singleton.class) {    //
             if (instance == null) {         //Read Write
                 instance = new Singleton(); //
             }
         }
     }
 }

Cum se creează un obiect singleton într-un mediu sigur pentru fire?

public static Singleton getInstance() {
   if (instance == null)
    instance = new Singleton();
}

Dacă creați un obiect Singleton din fire diferite, atunci poate exista o situație în care mai multe obiecte sunt create în același timp, iar acest lucru este inacceptabil. Prin urmare, este rezonabil să includeți crearea obiectului într-o instrucțiune sincronizată.

public static Singleton getInstance() {
    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

Această abordare va funcționa, dar are un mic dezavantaj. După ce obiectul este creat, de fiecare dată când încercați să îl obțineți în viitor, se va efectua o verificare în blocul sincronizat, ceea ce înseamnă că firul curent și tot ceea ce este legat de acesta va fi blocat. Deci acest cod poate fi puțin optimizat:

public static Singleton getInstance() {
     if (instance != null)
        return instance;

    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

Pe unele limbi și/sau pe unele mașini nu este posibilă implementarea în siguranță a acestui model. Prin urmare, uneori este numit un anti-model. Astfel de caracteristici au dus la apariția relației de ordine strictă „se întâmplă înainte” în Modelul de memorie Java și Modelul de memorie C++.

Este de obicei folosit pentru a reduce suprasarcina de implementare a inițializării leneșe în programe cu mai multe fire, cum ar fi modelul de proiectare Singleton. La inițializarea leneșă a unei variabile, inițializarea este amânată până când valoarea variabilei este necesară în calcul.

3.5 Programator

Scheduler este un model de proiectare paralel care oferă un mecanism pentru implementarea unei politici de planificare, dar este independent de orice politică particulară. Controlează ordinea în care firele de execuție ar trebui să execute codul secvențial, folosind un obiect care specifică în mod explicit secvența firelor de execuție în așteptare.

1
Sarcină
Modulul 3,  nivellecţie
Blocat
Trust, but Verify
task4123
Comentarii
  • Popular
  • Nou
  • Vechi
Trebuie să fii conectat pentru a lăsa un comentariu
Această pagină nu are încă niciun comentariu