Java minnesmodell
Java -minnesmodellen beskriver hur trådar i programmeringsspråket Java interagerar genom minnet. Tillsammans med beskrivningen av enkeltrådad exekvering av kod tillhandahåller minnesmodellen Java-programmeringsspråkets semantik .
Den ursprungliga Java-minnesmodellen som utvecklades 1995, uppfattades allmänt som trasig, vilket förhindrade många körtidsoptimeringar och gav inte tillräckligt starka garantier för kodsäkerhet. Den uppdaterades genom Java Community Process , som Java Specification Request 133 (JSR-133), som trädde i kraft redan 2004, för Tiger (Java 5.0) .
Sammanhang
Java -programmeringsspråket och plattformen tillhandahåller trådfunktioner . Synkronisering mellan trådar är notoriskt svårt för utvecklare; denna svårighet förvärras eftersom Java-applikationer kan köras på ett brett utbud av processorer och operativsystem . För att kunna dra slutsatser om ett programs beteende, bestämde sig Javas designers att de var tvungna att tydligt definiera möjliga beteenden för alla Java-program.
På moderna plattformar exekveras koden ofta inte i den ordning den skrevs. Det ordnas om av kompilatorn, processorn och minnesundersystemet för att uppnå maximal prestanda. På flerprocessorarkitekturer kan enskilda processorer ha sina egna lokala cachar som inte är synkroniserade med huvudminnet. Det är i allmänhet oönskat att kräva att trådar förblir perfekt synkroniserade med varandra eftersom detta skulle vara för kostsamt ur prestandasynpunkt. Det betyder att vid varje given tidpunkt kan olika trådar se olika värden för samma delade data.
I en entrådig miljö är det lätt att resonera kring kodexekvering. Det typiska tillvägagångssättet kräver att systemet implementerar som-om-seriell semantik för enskilda trådar isolerat. När en enskild tråd körs kommer det att se ut som om alla åtgärder som vidtas av den tråden sker i den ordning de visas i programmet, även om själva åtgärderna inte fungerar.
Om en tråd exekverar sina instruktioner i ur ordning, då kan en annan tråd se det faktum att dessa instruktioner kördes i ur ordning, även om det inte påverkade semantiken i den första tråden. Tänk till exempel på två trådar med följande instruktioner, som körs samtidigt, där variablerna x och y båda initieras till 0:
Tråd 1 | Tråd 2 |
---|---|
x = 1; | int rl = y; |
y = 2; | int r2 = x; |
Om inga omordningar utförs och läsningen av y i tråd 2 returnerar värdet 2, bör den efterföljande läsningen av x returnera värdet 1, eftersom skrivningen till x utfördes innan skrivningen till y. Men om de två skrivningarna ordnas om kan läsningen av y returnera värdet 2, och läsningen av x kan returnera värdet 0.
Java Memory Model (JMM) definierar det tillåtna beteendet för flertrådade program och beskriver därför när sådana omordningar är möjliga. Det sätter begränsningar för körningstid på förhållandet mellan trådar och huvudminne för att uppnå konsekventa och pålitliga Java-applikationer. Genom att göra detta gör det möjligt att resonera kring kodexekvering i en flertrådad miljö, även inför optimeringar som utförs av den dynamiska kompilatorn, processorerna och cacharna.
Minnesmodellen
För utförande av en enda tråd är reglerna enkla. Java -språkspecifikationen kräver en virtuell Java-maskin för att observera inom-tråden som-om-seriell semantik. Körtiden (som i det här fallet vanligtvis hänvisar till den dynamiska kompilatorn, processorn och minnesundersystemet) är fri att införa alla användbara exekveringsoptimeringar så länge resultatet av tråden isolerat garanteras vara exakt detsamma som det skulle ha varit om alla uttalanden hade körts i den ordning som satserna inträffade i programmet (även kallad programordning).
Den stora varningen med detta är att som-om-seriell semantik inte hindrar olika trådar från att ha olika syn på data. Minnesmodellen ger tydlig vägledning om vilka värden som får returneras när data läses. De grundläggande reglerna innebär att individuella åtgärder kan omordnas, så länge som trådens som-om-seriella semantik inte kränks, och åtgärder som innebär kommunikation mellan trådar, såsom förvärv eller frigöring av ett lås , säkerställer att åtgärder som hända före dem ses av andra trådar som ser deras effekter. Till exempel, allt som händer innan ett lås släpps kommer att ses vara beställt före och synligt för allt som händer efter ett efterföljande förvärv av samma lås.
Matematiskt finns det en delordning som kallas händer-före -ordningen över alla åtgärder som utförs av programmet. Händer -före -ordern subsumerar programordningen; om en åtgärd inträffar före en annan i programordningen, kommer den att ske före den andra i händer-före- ordningen. Dessutom bildar släpp och efterföljande förvärv av lås kanter i händer-före-grafen. En läsning är tillåten att returnera värdet för en skrivning om den skrivningen är den sista skrivningen till den variabeln före läsningen längs någon väg i händer- före- ordningen, eller om skrivningen inte är ordnad i förhållande till den läsningen i händelse- innan beställning.
Påverkan
Java-minnesmodellen var det första försöket att tillhandahålla en heltäckande minnesmodell för ett populärt programmeringsspråk. Det motiverades av den ökande förekomsten av samtidiga och parallella system, och behovet av att tillhandahålla verktyg och teknologier med tydlig semantik för sådana system. Sedan dess har behovet av en minnesmodell blivit mer allmänt accepterat, med liknande semantik tillhandahålls för språk som C++ .
Se även
externa länkar
- Java teori och praktik: Fixing the Java Memory Model, del 1 - En artikel som beskriver problem med den ursprungliga Java-minnesmodellen.
- Java teori och praktik: Fixing the Java Memory Model, del 2 - Förklarar ändringarna JSR 133 gjort i Java Memory Model.
- Java Memory Model Pragmatics (transkription)
- Java-minnesmodellen länkar
- Java intern struktur
- JSR-133 webbsida
- JSR-133 Vanliga frågor
- JSR-133 implementeringsguide