Modelul de memorie Java

Modelul de memorie Java (Engl. Java de memorie model. JMM) descrie comportamentul fluxurilor în mediul de execuție Java. Modelul de memorie - o parte din semantica limbajului Java, și descrie ceea ce se poate și ce nu trebuie să se aștepte programatorii în curs de dezvoltare software-ul nu este pentru un anumit Java-mașină, și pentru Java ca un întreg.

  • Sau fiecare act de acces la single - chiar și atunci când obiectul este creat pentru o lungă perioadă de timp și nimic nu poate fi schimbat - va provoca o blocare fir.
  • Sau, în anumite circumstanțe, sistemul va neterminat singur.
  • Sau, în anumite circumstanțe, sistemul va crea două single-uri.
  • Fie de design va depinde de comportamentul particular al unei anumite mașini.

Limbajul de programare Java vă permite să scrie programe multi-threaded. Deoarece Java poate rula pe o varietate de procesoare și sisteme de operare, sincronizare fir este deosebit de dificilă. Deci, programator poate face orice concluzii cu privire la comportamentul programelor, dezvoltatorii Java a decis să definească în mod clar diferitele comportamente ale programului Java.

Pe computerele moderne pentru codul de viteză este executat într-o ordine diferită în care în scris. Permutare efectuate de compilator, procesorul și subsistemul de memorie. Pe mașinile multiprocesor, fiecare nucleu poate avea propriul cache. nu sincronă cu memoria principală. Deci, procesoare diferite pot fi valori diferite, în același timp, la aceeași variabilă. Atunci când mai multe fire interacționează unele cu altele, este de obicei de dorit: să fie conștienți de un alt procesor, aveți nevoie de o mulțime de timp.

În plus față de mediul de un singur fir este suficientă pentru a solicita sistemului „psevdoposledovatelnogo“ a programului - observatorul, care vede numai de intrare-ieșire, s-ar părea că toate acțiunile sunt efectuate în ordinea în care au apărut în program, chiar dacă nu este. Cu toate acestea, oricine poate „vedea“ în memoria calculatorului - inclusiv un alt fir - toate aceste „trucuri“ vor fi vizibile. Luați în considerare două fluxuri, care funcționează simultan un cod (x și y inițial zerouri).

Dacă nu există nici o permutare, iar fluxul de gândire 2 y = 2. este garantat să fie x = 1. după intrarea în x este efectuată înainte de a înregistra în y. Cu permutare este posibil, și situația aparent paradoxală: r1 = 2. r2 = 0.

Acest comportament este de programe multi-threaded, modelul permite MJM, dar descrie atunci când sunt posibile permutări. Astfel, modelul de memorie Java limitează interacțiunea fluxurilor, astfel încât să nu piardă ocazia de a optimiza și în același timp să permită programelor multithreaded să se comporte în mod previzibil și sigur în cazul în care ar trebui să fie. Programatorul poate trage concluzii cu privire la ordinea în care codul se execută pe un multi-threaded a mașinii, chiar dacă optimizarea efectuată de compilator, și cache-ul procesorului.

Regula numarul 1: programe pe un singur fir sunt executate psevdoposledovatelno. Acest lucru înseamnă, în realitate, procesorul poate efectua mai multe operații pe ciclu de ceas, în același timp, schimba ordinea lor, dar toate dependențele de date sunt, astfel încât comportamentul nu diferă de serial.

Regula numărul 2: nu există nicăieri care au luat valori. Citind orice variabilă (cu excepția celor de lungă non-volatilă și dublu. Pentru care această regulă nu poate fi realizată) va da o valoare implicită (zero), sau ceva în scris cealaltă echipă.

Și Regula numărul 3: Restul evenimentelor sunt executate în ordine, dacă este legat prin ordin strict parțială „este executată înainte“ (în engleză se întâmplă înainte.).

„Running primul“

Modelul de memorie Java

lanț Cele două fluxuri a fost găsit „se efectuează înainte“ (curbe desemnate parțiale simbol ordine „mai puțin“) - afiseaza deci println valoarea corectă.

„Running înainte“ (în engleză se întâmplă înainte.) - ordine strictă parțială (arefleksivnoe, antisimetric, tranzitiv) a introdus între comenzile atomice (++ si - nu atomica), inventat de Leslie Lamport și nu înseamnă „fizic înainte.“ Aceasta înseamnă că a doua comandă va fi „conștient“ de schimbările efectuate mai întâi.

În special, unul executat înaintea celuilalt pentru astfel de tranzacții (lista nu este exhaustivă):

  • Sincronizarea și monitoare.
    • Monitor Capture (începutul sincronizate. blocare metodă) și totul după ce, în același fir.
    • Monitor de retur (sfârșitul sincronizate. Metoda de deblocare), și tot ce este în fața lui, în același fir.
      • Astfel, optimizatorul poate intra într-un bloc de sincronizare linie, dar nu spre exterior.
    • Întoarceți monitorul și capturarea ulterioară a unui alt fir.
  • Scrierea și citirea:
    • Orice dependență de date (adică post în orice variabilă și citirea sa ulterioară aceeași) într-un singur flux.
    • Tot ceea ce este în același fir înainte de a scrie la -variable volatile, iar înregistrarea în sine.
    • -CITEȘTE volatile și totul după ce, în același fir.
    • Entry volatile -variable și citesc ca ulterior [2] [4]. Astfel, este volatil -record face aceeași memorie că revenirea monitorului, și citirea - la fel ca și capturarea [5]. Acest lucru înseamnă că, în cazul în care un fir este înregistrat în -variable volatile, iar al doilea este găsit, tot ce precede înregistrarea este realizată înainte de tot ceea ce vine după lectura; cm. ilustrare.
      • Pentru variabilele obiect (de exemplu, volatile Listă x;) o astfel de garanție puternică sunt efectuate pentru o referință obiect, dar nu pentru conținutul său.
  • întreţinere:
    • Inițializarea statică și orice acțiune cu orice instanță obiect.
    • Scrierea în câmpul final al constructorului [6], și tot ce după constructor. Ca o excepție de la tranzitive generală, se întâmplă înainte de a-relație nu este tranzitiv în legătură cu alte reguli și, prin urmare, poate provoca o cursă-fir [7].
    • Orice lucru cu obiectul și finaliza ().
  • Serviciul Debit:
    • Pornind de flux și orice cod în flux.
    • Dispariția variabilelor legate de fluxul, precum și orice cod în flux.
    • un flux de cod și să se alăture (); flux de cod și isAlive () == false.
    • întrerupere (), precum și faptul detectare de oprire a fluxului.

Datorită implementării pe scară largă a sistemelor multi-threaded și paralele necesare instrumente cu o semantica clară. Modelul de memorie Java este prima încercare de a dezvolta un model comprehensiv de interacțiune inter-thread pentru limbajul de programare pe scară largă. [8]

În C ++ 03, singura remarcă despre filetare - de exemplu variabile volatile nu efectuează orice optimizări legate de accesul accelerare. Acest lucru este, de asemenea, nu este suficient pentru a permite completă noduri de schimb de putere compilator / procesor și nu primesc eroarea asociată cu performanța extraordinară a unor echipe. Un model similar de memorie inclus în 11 C ++ [9].