Cuvântul cheie volatil este folosit pentru a modifica valoarea unei variabile prin diferite fire. Este, de asemenea, folosit pentru a face clasele în siguranță. Înseamnă că mai multe fire pot folosi o metodă și o instanță a claselor în același timp, fără nicio problemă. Cuvântul cheie volatil poate fi folosit fie cu tipul primitiv, fie cu obiecte.
Cuvântul cheie volatil nu memorează în cache valoarea variabilei și citește întotdeauna variabila din memoria principală. Cuvântul cheie volatil nu poate fi folosit cu clase sau metode. Cu toate acestea, este folosit cu variabile. De asemenea, garantează vizibilitatea și comanda. Împiedică compilatorul să reordoneze codul.
Conținutul unui anumit registru al dispozitivului se poate modifica în orice moment, așa că aveți nevoie de cuvântul cheie volatil pentru a vă asigura că astfel de accesări nu sunt optimizate de către compilator.
starea git
Exemplu
class Test { static int var=5; }
În exemplul de mai sus, presupunem că două fire lucrează pe aceeași clasă. Ambele fire rulează pe procesoare diferite, unde fiecare fir are copia locală a lui var. Dacă orice fir își modifică valoarea, modificarea nu se va reflecta în cel original din memoria principală. Aceasta duce la inconsecvența datelor deoarece celălalt thread nu este conștient de valoarea modificată.
class Test { static volatile int var =5; }
În exemplul de mai sus, variabilele statice sunt membri de clasă care sunt partajați între toate obiectele. Există o singură copie în memoria principală. Valoarea unei variabile volatile nu va fi niciodată stocată în cache. Toate citirea și scrierea se vor face din și către memoria principală.
comunicare analogică
Când să-l folosești?
- Puteți utiliza o variabilă volatilă dacă doriți să citiți și să scrieți automat variabile lungi și duble.
- Poate fi folosit ca o modalitate alternativă de realizare a sincronizării în Java.
- Toate firele de execuție vor vedea valoarea actualizată a variabilei volatile după finalizarea operației de scriere. Dacă nu utilizați cuvântul cheie volatil, un fir de citire diferit poate vedea valori diferite.
- Este folosit pentru a informa compilatorul că mai multe fire vor accesa o anumită instrucțiune. Împiedică compilatorul să facă orice reordonare sau orice optimizare.
- Dacă nu utilizați compilatorul de variabile volatile, puteți reordona codul, puteți scrie în cache valoarea variabilei volatile în loc să citiți din memoria principală.
Puncte importante
- Puteți utiliza cuvântul cheie volatil cu variabile. Utilizarea cuvintelor cheie volatile cu clase și metode este ilegală.
- Acesta garantează că valoarea variabilei volatile va fi întotdeauna citită din memoria principală, nu din memoria cache locală.
- Dacă ați declarat variabila ca fiind volatilă, citirea și scrierea sunt atomice
- Reduce riscul erorii de consistență a memoriei.
- Orice scriere într-o variabilă volatilă în Java stabilește o întâmplare înainte de relația cu citirile succesive ale aceleiași variabile.
- Variabilele volatile sunt întotdeauna vizibile pentru alte fire.
- Variabila volatilă care este o referință la obiect poate fi nulă.
- Atunci când o variabilă nu este partajată între mai multe fire, nu trebuie să utilizați cuvântul cheie volatil cu acea variabilă.
Diferența dintre sincronizare și cuvânt cheie volatil
Cuvântul cheie volatil nu este un substitut al cuvântului cheie sincronizat, dar poate fi folosit ca alternativă în anumite cazuri. Există următoarele diferențe sunt după cum urmează:
Cuvânt cheie volatil | Cuvânt cheie de sincronizare |
---|---|
Cuvântul cheie volatil este un modificator de câmp. | Cuvântul cheie sincronizat modifică blocurile de cod și metodele. |
Firul nu poate fi blocat pentru așteptare în caz de volatilitate. | Firele pot fi blocate pentru așteptare în caz de sincronizare. |
Îmbunătățește performanța firului. | Metodele sincronizate degradează performanța firului de execuție. |
Sincronizează valoarea unei variabile la un moment dat între memoria firului și memoria principală. | Sincronizează valoarea tuturor variabilelor între memoria firului și memoria principală. |
Câmpurile volatile nu sunt supuse optimizării compilatorului. | Sincronizarea este supusă optimizării compilatorului. |
Exemplu de cuvânt cheie volatil
În exemplul următor, am definit o clasă care mărește valoarea contorului. Metoda run () din VolatileThread.java primește valoarea actualizată și valoarea veche atunci când firul începe execuția. În clasa principală, definim matricea de fire.
VolatileData.java
curățați memoria cache npm
public class VolatileData { private volatile int counter = 0; public int getCounter() { return counter; } public void increaseCounter() { ++counter; //increases the value of counter by 1 } }
Volatile Thread.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;>