CodeGym/Java kursus/Modul 3/Hukommelse i JVM, del 2

Hukommelse i JVM, del 2

Ledig

Hukommelse hardware arkitektur

Moderne hukommelseshardwarearkitektur adskiller sig fra Javas interne hukommelsesmodel. Derfor skal du forstå hardwarearkitekturen for at vide, hvordan Java-modellen fungerer med den. Dette afsnit beskriver den generelle hukommelseshardwarearkitektur, og det næste afsnit beskriver, hvordan Java fungerer med det.

Her er et forenklet diagram over hardwarearkitekturen på en moderne computer:

Hukommelse hardware arkitektur

I den moderne verden har en computer 2 eller flere processorer, og dette er allerede normen. Nogle af disse processorer kan også have flere kerner. På sådanne computere er det muligt at køre flere tråde på samme tid. Hver processorkerne er i stand til at udføre en tråd på ethvert givet tidspunkt. Det betyder, at enhver Java-applikation på forhånd er multi-threaded, og i dit program kan én tråd pr. processorkerne køre ad gangen.

Processorkernen indeholder et sæt registre, der ligger i dens hukommelse (inde i kernen). Den udfører operationer på registerdata meget hurtigere end på data, der ligger i computerens hovedhukommelse (RAM). Dette skyldes, at processoren kan få adgang til disse registre meget hurtigere.

Hver CPU kan også have sit eget cachelag. De fleste moderne processorer har det. Processoren kan få adgang til sin cache meget hurtigere end hovedhukommelsen, men ikke så hurtigt som dens interne registre. Værdien af ​​cache-adgangshastigheden er omtrent mellem adgangshastighederne for hovedhukommelsen og interne registre.

Desuden har processorer et sted at have en multi-level cache. Men dette er ikke så vigtigt at vide for at forstå, hvordan Java-hukommelsesmodellen interagerer med hardwarehukommelse. Det er vigtigt at vide, at processorer kan have et niveau af cache.

Enhver computer indeholder også RAM (hovedhukommelsesområde) på samme måde. Alle kerner kan få adgang til hovedhukommelsen. Hovedhukommelsesområdet er normalt meget større end processorkernernes cachehukommelse.

I det øjeblik, hvor processoren har brug for adgang til hovedhukommelsen, læser den en del af den ind i sin cachehukommelse. Det kan også læse nogle data fra cachen ind i dets interne registre og derefter udføre operationer på dem. Når CPU'en skal skrive resultatet tilbage til hovedhukommelsen, vil den tømme dataene fra dets interne register til cache og på et tidspunkt til hovedhukommelsen.

Data gemt i cachen skylles normalt tilbage til hovedhukommelsen, når processoren skal gemme noget andet i cachen. Cachen har mulighed for at rydde sin hukommelse og skrive data på samme tid. Processoren behøver ikke at læse eller skrive den fulde cache hver gang under en opdatering. Normalt opdateres cachen i små hukommelsesblokke, de kaldes "cache-linje". En eller flere "cache-linjer" kan læses ind i cache-hukommelsen, og en eller flere cache-linjer kan tømmes tilbage til hovedhukommelsen.

Kombinerer Java-hukommelsesmodel og hukommelseshardwarearkitektur

Som allerede nævnt er Java-hukommelsesmodellen og hukommelseshardwarearkitekturen forskellige. Hardwarearkitekturen skelner ikke mellem trådstakke og dynger. På hardware ligger trådstakken og HEAP (heap) i hovedhukommelsen.

Dele af stakke og tråddynger kan nogle gange være til stede i caches og interne registre i CPU'en. Dette er vist i diagrammet:

trådstabel og HEAP

Når objekter og variabler kan lagres i forskellige områder af computerens hukommelse, kan der opstå visse problemer. Her er de to vigtigste:

  • Synlighed af de ændringer, som tråden har foretaget i delte variabler.
  • Race tilstand ved læsning, kontrol og skrivning af delte variable.

Begge disse spørgsmål vil blive forklaret nedenfor.

Synlighed af delte objekter

Hvis to eller flere tråde deler et objekt uden korrekt brug af flygtig deklaration eller synkronisering, er ændringer af det delte objekt foretaget af én tråd muligvis ikke synlige for andre tråde.

Forestil dig, at et delt objekt oprindeligt er gemt i hovedhukommelsen. En tråd, der kører på en CPU, læser det delte objekt ind i cachen på den samme CPU. Der foretager han ændringer i objektet. Indtil CPU'ens cache er blevet tømt til hovedhukommelsen, er den ændrede version af det delte objekt ikke synlig for tråde, der kører på andre CPU'er. Således kan hver tråd få sin egen kopi af det delte objekt, hver kopi vil være i en separat CPU-cache.

Følgende diagram illustrerer en oversigt over denne situation. En tråd, der kører på den venstre CPU, kopierer det delte objekt ind i sin cache og ændrer værdien af ​​count til 2. Denne ændring er usynlig for andre tråde, der kører på den højre CPU, fordi opdateringen til at tælle endnu ikke er blevet tømt tilbage til hovedhukommelsen.

For at løse dette problem kan du bruge det flygtige nøgleord, når du erklærer en variabel. Det kan sikre, at en given variabel læses direkte fra hovedhukommelsen og altid skrives tilbage til hovedhukommelsen, når den opdateres.

Race tilstand

Hvis to eller flere tråde deler det samme objekt, og mere end én tråd opdaterer variabler i det delte objekt, kan der opstå en racetilstand.

Forestil dig, at tråd A læser det delte objekts tællevariabel ind i dets processors cache. Forestil dig også, at tråd B gør det samme, men i en anden processors cache. Nu tilføjer tråd A 1 til værdien af ​​tæller, og tråd B gør det samme. Nu er variablen blevet øget to gange - separat med +1 i hver processors cache.

Hvis disse trin blev udført sekventielt, ville tællevariablen blive fordoblet og skrevet tilbage til hovedhukommelsen (oprindelig værdi + 2).

Der blev dog udført to trin på samme tid uden ordentlig synkronisering. Uanset hvilken tråd (A eller B) der skriver sin opdaterede version af tæller til hovedhukommelsen, vil den nye værdi kun være 1 mere end den oprindelige værdi, på trods af de to trin.

Dette diagram illustrerer forekomsten af ​​racebetingelsesproblemet beskrevet ovenfor:

For at løse dette problem kan du bruge Java-synkroniseret blok. En synkroniseret blok sikrer, at kun én tråd kan indtaste en given kritisk sektion af kode på et givet tidspunkt.

Synkroniserede blokke garanterer også, at alle variabler, der er adgang til inde i den synkroniserede blok, vil blive læst fra hovedhukommelsen, og når tråden forlader den synkroniserede blok, vil alle opdaterede variable blive tømt tilbage til hovedhukommelsen, uanset om variablen er erklæret flygtig eller Nej.

Kommentarer
  • Populær
  • Ny
  • Gammel
Du skal være logget ind for at skrive en kommentar
Denne side har ingen kommentarer endnu