Nepastovus raktinis žodis naudojamas kintamojo reikšmei modifikuoti skirtingomis gijomis. Jis taip pat naudojamas, kad klasių siūlai būtų saugūs. Tai reiškia, kad kelios gijos gali naudoti metodą ir klasių egzempliorių tuo pačiu metu be jokių problemų. Nepastovus raktinis žodis gali būti naudojamas su primityviu tipu arba objektais.
duomenų struktūra
Nepastovus raktinis žodis nelaiko kintamojo reikšmės talpykloje ir visada nuskaito kintamąjį iš pagrindinės atminties. Nepastovus raktinis žodis negali būti naudojamas su klasėmis ar metodais. Tačiau jis naudojamas su kintamaisiais. Tai taip pat garantuoja matomumą ir užsakymą. Tai neleidžia kompiliatoriui pertvarkyti kodą.
Konkretaus įrenginio registro turinys gali bet kada pasikeisti, todėl jums reikia nepastovaus raktinio žodžio, kad užtikrintumėte, jog tokių prieigų neoptimizuotų kompiliatorius.
Pavyzdys
class Test { static int var=5; }
Aukščiau pateiktame pavyzdyje tarkime, kad dvi gijos dirba toje pačioje klasėje. Abi gijos veikia skirtinguose procesoriuose, kur kiekviena gija turi vietinę var kopiją. Jei kuri nors gija pakeičia jo reikšmę, pakeitimas neatsispindės pradinėje pagrindinėje atmintyje. Tai veda prie duomenų nenuoseklumo, nes kita gija nežino pakeistos vertės.
class Test { static volatile int var =5; }
Pirmiau pateiktame pavyzdyje statiniai kintamieji yra klasės nariai, kurie yra bendrinami visiems objektams. Pagrindinėje atmintyje yra tik viena kopija. Nepastovaus kintamojo reikšmė niekada nebus saugoma talpykloje. Viskas bus skaitoma ir rašoma iš pagrindinės atminties ir į ją.
Kada jį naudoti?
- Galite naudoti nepastovų kintamąjį, jei norite automatiškai skaityti ir rašyti ilgą ir dvigubą kintamąjį.
- Jis gali būti naudojamas kaip alternatyvus būdas sinchronizuoti Java.
- Visos skaitytuvo gijos matys atnaujintą nepastovaus kintamojo reikšmę, kai bus baigta rašymo operacija. Jei nenaudojate nepastovaus raktinio žodžio, skirtingos skaitytojo grupės gali matyti skirtingas reikšmes.
- Jis naudojamas informuoti kompiliatorių, kad kelios gijos pasieks konkretų teiginį. Tai neleidžia kompiliatoriui atlikti pertvarkymo ar optimizavimo.
- Jei nenaudojate nepastovus kintamasis, kompiliatorius gali pertvarkyti kodą, laisvai įrašyti nepastoviojo kintamojo talpyklos reikšmę, o ne skaityti iš pagrindinės atminties.
Svarbūs punktai
- Galite naudoti nepastovų raktinį žodį su kintamaisiais. Nepastovų raktažodžių naudojimas su klasėmis ir metodais yra neteisėtas.
- Tai garantuoja, kad nepastovaus kintamojo reikšmė visada bus skaitoma iš pagrindinės atminties, o ne iš vietinės gijos talpyklos.
- Jei kintamąjį paskelbėte kaip nepastovų, skaitymo ir rašymo funkcijos yra atominės
- Tai sumažina atminties nuoseklumo klaidų riziką.
- Bet koks „Java“ rašymas į nepastovų kintamąjį nustato įvykį prieš ryšį su to paties kintamojo nuosekliais skaitymais.
- Nepastovus kintamuosius visada mato kitos gijos.
- Nepastovus kintamasis, kuris yra objekto nuoroda, gali būti nulinis.
- Kai kintamasis nėra bendrinamas tarp kelių gijų, su tuo kintamuoju nereikia naudoti nepastovaus raktinio žodžio.
Skirtumas tarp sinchronizavimo ir nepastovaus raktinio žodžio
Nepastovus raktinis žodis nėra sinchronizuoto raktinio žodžio pakaitalas, tačiau kai kuriais atvejais jis gali būti naudojamas kaip alternatyva. Yra šie skirtumai:
Nepastovus raktinis žodis | Sinchronizavimo raktinis žodis |
---|---|
Nepastovus raktinis žodis yra lauko modifikatorius. | Sinchronizuotas raktinis žodis modifikuoja kodų blokus ir metodus. |
Siūlas negali būti užblokuotas laukimui esant nepastoviam. | Sinchronizavimo atveju gijos gali būti užblokuotos laukti. |
Tai pagerina siūlų veikimą. | Sinchronizuoti metodai pablogina gijos veikimą. |
Jis vienu metu sinchronizuoja vieno kintamojo reikšmę tarp gijų atminties ir pagrindinės atminties. | Jis sinchronizuoja visų kintamųjų vertes tarp gijų atminties ir pagrindinės atminties. |
Nepastoviems laukams netaikomas kompiliatoriaus optimizavimas. | Sinchronizavimas priklauso nuo kompiliatoriaus optimizavimo. |
Nepastovaus raktinio žodžio pavyzdys
Šiame pavyzdyje apibrėžėme klasę, kuri padidina skaitiklio reikšmę. Vykdymo () metodas VolatileThread.java gauna atnaujintą vertę ir seną vertę, kai gija pradeda vykdyti. Pagrindinėje klasėje apibrėžiame gijų masyvą.
VolatileData.java
public class VolatileData { private volatile int counter = 0; public int getCounter() { return counter; } public void increaseCounter() { ++counter; //increases the value of counter by 1 } }
VolatileThread.java
VolatileThread.java public class VolatileThread extends Thread { private final VolatileData data; public VolatileThread(VolatileData data) { this.data = data; } @Override public void run() { int oldValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: Old value = ' + oldValue); data.increaseCounter(); int newValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: New value = ' + newValue); } }
VolatileMain.java
public class VolatileMain { private final static int noOfThreads = 2; public static void main(String[] args) throws InterruptedException { VolatileData volatileData = new VolatileData(); //object of VolatileData class Thread[] threads = new Thread[noOfThreads]; //creating Thread array for(int i = 0; i <noofthreads; ++i) threads[i]="new" volatilethread(volatiledata); for(int i="0;" < noofthreads; threads[i].start(); starts all reader threads threads[i].join(); wait for } pre> <p> <strong>Output:</strong> </p> <pre> [Thread 9]: Old value = 0 [Thread 9]: New value = 1 [Thread 10]: Old value = 1 [Thread 10]: New value = 2 </pre> <hr></noofthreads;>