Ключовата дума volatile се използва за промяна на стойността на променлива от различни нишки. Също така се използва, за да направи класовете нишково безопасни. Това означава, че множество нишки могат да използват метод и екземпляр на класовете едновременно без проблем. Ключовата дума volatile може да се използва или с примитивен тип, или с обекти.
Ключовата дума volatile не кешира стойността на променливата и винаги чете променливата от основната памет. Ключовата дума volatile не може да се използва с класове или методи. Въпреки това се използва с променливи. Освен това гарантира видимост и подреденост. Той не позволява на компилатора да пренареди кода.
Съдържанието на конкретния регистър на устройството може да се промени по всяко време, така че имате нужда от ключовата дума volatile, за да сте сигурни, че такива достъпи не се оптимизират от компилатора.
Пример
class Test { static int var=5; }
В горния пример приемете, че две нишки работят върху един и същи клас. И двете нишки работят на различни процесори, където всяка нишка има свое локално копие на var. Ако някоя нишка промени стойността си, промяната няма да се отрази в оригиналната в основната памет. Това води до несъответствие в данните, тъй като другата нишка не е наясно с модифицираната стойност.
class Test { static volatile int var =5; }
В горния пример статичните променливи са членове на класа, които се споделят между всички обекти. Има само едно копие в основната памет. Стойността на променлива променлива никога няма да се съхранява в кеша. Цялото четене и запис ще се извършва от и към основната памет.
Кога да го използвам?
- Можете да използвате променлива променлива, ако искате автоматично да четете и записвате дълго и двойно променлива.
- Може да се използва като алтернативен начин за постигане на синхронизация в Java.
- Всички нишки за четене ще видят актуализираната стойност на променливата volatile след завършване на операцията за запис. Ако не използвате ключовата дума volatile, различни нишки на читатели може да виждат различни стойности.
- Използва се за информиране на компилатора, че множество нишки ще имат достъп до определен оператор. Това не позволява на компилатора да извършва пренареждане или каквато и да е оптимизация.
- Ако не използвате променлива променлива, компилаторът може да пренареди кода, свободно да записва в кеша стойността на променлива променлива, вместо да чете от основната памет.
Важни точки
- Можете да използвате ключовата дума volatile с променливи. Използването на ключова дума volatile с класове и методи е незаконно.
- Той гарантира, че стойността на променливата volatile винаги ще се чете от основната памет, а не от локалния кеш на нишката.
- Ако сте декларирали променлива като volatile, четенето и записът са атомарни
- Намалява риска от грешка в последователността на паметта.
- Всеки запис в променлива променлива в Java установява събитие преди връзката с последователни четения на същата променлива.
- Променливите променливи винаги са видими за други нишки.
- Променливата променлива, която е препратка към обект, може да е нулева.
- Когато една променлива не се споделя между множество нишки, не е необходимо да използвате ключовата дума volatile с тази променлива.
Разлика между синхронизация и променлива ключова дума
Променливата ключова дума не е заместител на синхронизираната ключова дума, но може да се използва като алтернатива в определени случаи. Има следните разлики, както следва:
Летлива ключова дума | Ключова дума за синхронизиране |
---|---|
Ключовата дума volatile е модификатор на полето. | Синхронизираната ключова дума променя кодовите блокове и методи. |
Нишката не може да бъде блокирана за изчакване в случай на volatile. | Нишките могат да бъдат блокирани за изчакване в случай на синхронизиране. |
Подобрява производителността на нишката. | Синхронизираните методи влошават производителността на нишката. |
Той синхронизира стойността на една променлива наведнъж между паметта на нишката и основната памет. | Той синхронизира стойността на всички променливи между паметта на нишката и основната памет. |
Променливите полета не подлежат на оптимизация на компилатора. | Синхронизирането подлежи на оптимизация на компилатора. |
Пример за променлива ключова дума
В следващия пример сме дефинирали клас, който увеличава стойността на брояча. Методът run () във VolatileThread.java получава актуализираната стойност и старата стойност, когато нишката започне да се изпълнява. В основния клас ние дефинираме масива от нишки.
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;>