Java minnesmodell

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 16 juli 2022; verifiering kräver 1 redigering .

Java Memory Model ( JMM ) beskriver beteendet hos trådar i Java runtime-miljön .  Minnesmodellen är en del av Java-språkets semantik , och beskriver vad en programmerare kan och inte bör förvänta sig när man utvecklar programvara inte för en specifik Java-maskin, utan för Java som helhet.

Den ursprungliga Java-minnesmodellen (som inkluderar "perkolokalt minne" i synnerhet), utvecklad 1995, anses vara ett misslyckande: många optimeringar kan inte göras utan att förlora garantin för kodsäkerhet. I synnerhet finns det flera alternativ för att skriva flertrådiga " enhands ": [1]

J2SE 5.0 ( 30 september 2004) introducerade en ny minnesmodell utvecklad genom Java Community Process kallad JSR-133 [2] [3] . Det återspeglade bättre hur moderna processorer och kompilatorer fungerar, och andra språk har hämtat idéer från Java-modellen. De viktigaste bidragen till dess skapelse gjordes av Sarita Adwe , Jeremy Mason och Bill Pugh [4] .

Bakgrund

Programmeringsspråket Java låter dig skriva flertrådade program. Eftersom Java kan köras på en mängd olika processorer och operativsystem är trådsynkronisering särskilt svårt. För att programmeraren skulle kunna dra några slutsatser om programmens beteende, bestämde sig Java-utvecklarna för att tydligt definiera de olika beteendena för alla Java-program.

På moderna datorer exekveras koden inte i den ordning som den skrivs för hastighetens skull. Permutationen görs av kompilatorn, processorn och minnesundersystemet. På multiprocessormaskiner kan varje kärna ha sin egen cache som inte är synkron med huvudminnet. Det betyder att olika processorer kan ha olika värden på samma variabel samtidigt. När trådar interagerar mycket med varandra är detta vanligtvis oönskat: det tar mycket tid att hålla sig à jour med vad den andra processorn har gjort.

Dessutom, i en enkeltrådad miljö, räcker det att kräva att systemet ska "pseudo-sekventiell" programkörning - för en observatör som bara ser I/O , kommer det att verka som att alla åtgärder utförs i den ordning som de dykt upp i programmet, även om de inte är det. Den som kan "titta" i datorns minne - inklusive en annan tråd - kommer dock att märkas av alla dessa "tricks". Tänk på två trådar som samtidigt exekverar sådan kod ( xoch yinitialt nollor).

Streama 1 Streama 2
x = 1; int rl = y;
y=2; int r2 = x;

Om det inte finns några permutationer, och tråd 2 läser y=2, är det garanterat x=1: trots allt, skrivningen till xutförs innan skrivningen till y. Med en permutation visar sig en till synes paradoxal situation vara möjlig: r1=2, r2=0.

JMM tillåter detta beteende för flertrådade program, men beskriver när sådana permutationer är möjliga. Java-minnesmodellen lägger alltså restriktioner på interaktionen mellan trådar för att inte förlora möjliga optimeringar och samtidigt tillåta flertrådade program att bete sig tillförlitligt och förutsägbart där det behövs. Programmeraren kan göra vilka slutsatser som helst om i vilken ordning koden exekveras på en flertrådad maskin, även trots de optimeringar som gjorts av kompilatorn, processorn och cachen.

Minnesmodell

Regel #1: Enkeltrådade program körs pseudo-sekventiellt. Detta betyder: i verkligheten kan processorn utföra flera operationer per klocka, samtidigt som de ändrar sin ordning, men alla databeroenden kvarstår, så beteendet skiljer sig inte från sekventiellt.

Regel nummer 2: det finns inga värden från ingenstans. Att läsa valfri variabel (förutom icke- volatile longoch double, för vilka denna regel kanske inte är sann) returnerar antingen standardvärdet (noll) eller något som skrivits där av ett annat kommando.

Och regel nummer 3: resten av händelserna exekveras i ordning, om de är sammankopplade med ett strikt partiell ordningsförhållande "utförs före" ( engelska  händer före ).

"Kör före"

"Happens before" ( engelska  happens before ) är en strikt partiell ordningsrelation (antireflexiv, antisymmetrisk, transitiv) införd mellan atomiska kommandon ( ++och --inte atomiska), uppfunnen av Leslie Lamport och betyder inte "fysiskt innan". Det betyder att det andra laget kommer att vara "medvetet" om ändringarna som gjorts av det första.

I synnerhet utförs den ena före den andra för sådana operationer (listan är inte uttömmande):

Inflytande

På grund av den utbredda introduktionen av flertrådiga och parallella system krävdes en verktygslåda med tydlig semantik. Java-minnesmodellen var det första försöket att utveckla en omfattande kommunikationsmodell mellan trådar för ett stort programmeringsspråk [9] .

I C++03 är den enda anmärkningen om multithreading att volatile-variabler inte har några accesshastighetsoptimeringar. Detta räckte inte heller för att använda den fulla kraften hos den omarrangerande kompilatorn/processorn och inte få ett fel relaterat till att ett kommando utfördes i oordning. En liknande minnesmodell inkluderades i C++11 [10] .

Se även

Anteckningar

  1. ↑ Deklarationen "dubbelkontrollerad låsning är trasig" . Hämtad 21 juli 2013. Arkiverad från originalet 6 mars 2012.
  2. 1 2 Goetz, Brian Fixing the Java Memory Model, del 2 (nedlänk) (24 februari 2004). Hämtad 18 oktober 2010. Arkiverad från originalet 8 januari 2007. 
  3. Jeremy Manson och Brian Goetz. JSR 133 (Java Memory Model) FAQ (februari 2004). — « Java-minnesmodellen beskriver vilka beteenden som är lagliga i flertrådad kod, och hur trådar kan interagera genom minnet. Den beskriver förhållandet mellan variabler i ett program och lågnivådetaljerna för att lagra och hämta dem till och från minne eller register i ett riktigt datorsystem. Den gör detta på ett sätt som kan implementeras korrekt med en mängd olika hårdvara och en mängd olika kompilatoroptimeringar. ". Datum för åtkomst: 18 oktober 2010. Arkiverad från originalet den 4 september 2013.
  4. James Gosling, Bill Joy, Guy L. Jr. Steele, Gilad Bracha, Alex Buckley. Java Language Specification, Java SE 7 Edition. - Pearson Education, 2013. - ISBN 978-0-13-326032-8 .
  5. Synkronisering och Java-minnesmodellen . Hämtad 21 juli 2013. Arkiverad från originalet 11 maj 2013.
  6. Kokboken JSR-133 (nedlänk) . Hämtad 18 juli 2013. Arkiverad från originalet 25 september 2013. 
  7. Ingenstans, förutom från konstruktorn, finalkan du inte skriva till -fields.
  8. >arbetsnoteringar: garantier för slutfält . Hämtad 22 juli 2013. Arkiverad från originalet 16 januari 2015.
  9. Goetz, Brian Fixing the Java Memory Model, Del 1 (nedlänk) (24 februari 2004). Hämtad 17 februari 2008. Arkiverad från originalet 13 augusti 2009. 
  10. Boehm, Hans Trådar och minnesmodell för C++ (nedlänk) . Datum för åtkomst: 17 februari 2008. Arkiverad från originalet den 4 september 2013. 

Länkar