Flygtigt nøgleord bruges til at ændre værdien af en variabel med forskellige tråde. Det bruges også til at gøre klasser trådsikre. Det betyder, at flere tråde kan bruge en metode og instans af klasserne på samme tid uden problemer. Det flygtige nøgleord kan bruges enten med primitiv type eller objekter.
Det flygtige nøgleord cachelagrer ikke værdien af variablen og læser altid variablen fra hovedhukommelsen. Det flygtige nøgleord kan ikke bruges med klasser eller metoder. Det bruges dog med variabler. Det garanterer også synlighed og bestilling. Det forhindrer compileren i at omarrangere kode.
Indholdet af det pågældende enhedsregister kan ændres til enhver tid, så du har brug for det flygtige nøgleord for at sikre, at sådanne adgange ikke optimeres væk af compileren.
Eksempel
class Test { static int var=5; }
Antag i ovenstående eksempel, at to tråde arbejder på samme klasse. Begge tråde kører på forskellige processorer, hvor hver tråd har sin lokale kopi af var. Hvis en tråd ændrer sin værdi, vil ændringen ikke afspejles i den originale i hovedhukommelsen. Det fører til datainkonsistens, fordi den anden tråd ikke er opmærksom på den ændrede værdi.
class Test { static volatile int var =5; }
I ovenstående eksempel er statiske variabler klassemedlemmer, der er delt mellem alle objekter. Der er kun én kopi i hovedhukommelsen. Værdien af en flygtig variabel vil aldrig blive gemt i cachen. Al læsning og skrivning vil foregå fra og til hovedhukommelsen.
Hvornår skal man bruge det?
- Du kan bruge en flygtig variabel, hvis du vil læse og skrive lang og dobbelt variabel automatisk.
- Det kan bruges som en alternativ måde at opnå synkronisering i Java.
- Alle læsetråde vil se den opdaterede værdi af den flygtige variabel efter at have afsluttet skriveoperationen. Hvis du ikke bruger det flygtige søgeord, kan en anden læsertråd se forskellige værdier.
- Det bruges til at informere compileren om, at flere tråde vil få adgang til en bestemt erklæring. Det forhindrer compileren i at foretage nogen genbestilling eller optimering.
- Hvis du ikke bruger volatile variabel compiler kan omarrangere koden, fri til at skrive i cache værdien af flygtige variable i stedet for at læse fra hovedhukommelsen.
Vigtige punkter
- Du kan bruge det flygtige søgeord med variabler. Brug af flygtige søgeord med klasser og metoder er ulovligt.
- Det garanterer, at værdien af den flygtige variabel altid vil blive læst fra hovedhukommelsen, ikke fra den lokale trådcache.
- Hvis du erklærede variabel som flygtig, er Read og Writes atomare
- Det reducerer risikoen for hukommelseskonsistensfejl.
- Enhver skrivning til flygtig variabel i Java etablerer en happening før forholdet med successive læsninger af den samme variabel.
- De flygtige variable er altid synlige for andre tråde.
- Den flygtige variabel, der er en objektreference, kan være nul.
- Når en variabel ikke er delt mellem flere tråde, behøver du ikke bruge det flygtige søgeord med denne variabel.
Forskellen mellem synkronisering og flygtigt søgeord
Flygtigt søgeord er ikke en erstatning for synkroniseret søgeord, men det kan bruges som et alternativ i visse tilfælde. Der er følgende forskelle:
Flygtigt søgeord | Synkronisering søgeord |
---|---|
Flygtigt nøgleord er en feltmodifikator. | Synkroniseret nøgleord ændrer kodeblokke og metoder. |
Tråden kan ikke blokeres for at vente i tilfælde af flygtig. | Tråde kan blokeres for at vente i tilfælde af synkronisering. |
Det forbedrer trådens ydeevne. | Synkroniserede metoder forringer trådens ydeevne. |
Den synkroniserer værdien af en variabel ad gangen mellem trådhukommelse og hovedhukommelse. | Det synkroniserer værdien af alle variable mellem trådhukommelse og hovedhukommelse. |
Flygtige felter er ikke genstand for compiler-optimering. | Synkronisering er underlagt compiler-optimering. |
Eksempel på flygtigt søgeord
I det følgende eksempel har vi defineret en klasse, som øger tællerværdien. Kør ()-metoden i VolatileThread.java får den opdaterede værdi og den gamle værdi, når tråden begynder at køre. I hovedklassen definerer vi rækken af tråde.
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;>