it-swarm-eu.dev

Používáte někdy volatilní klíčové slovo v jazyce Java?

Při práci jsem narazil na klíčové slovo volatile v Javě. Nebyl jsem velmi obeznámen s tím, našel jsem toto vysvětlení: 

Java teorie a praxe: Řízení volatility

Vzhledem k podrobnostem, v nichž tento článek vysvětluje dané klíčové slovo, používáte jej někdy nebo byste někdy viděli případ, ve kterém byste mohli toto klíčové slovo použít správným způsobem?

565
Richard

volatile má sémantiku pro viditelnost paměti. Hodnota pole volatile se v podstatě stane viditelnou pro všechny čtenáře (zejména ostatní vlákna) po dokončení operace zápisu. Bez volatile, čtenáři mohli vidět nějakou neaktualizovanou hodnotu.

Chcete-li odpovědět na svou otázku: Ano, pomocí proměnné volatile kontroluji, zda nějaký kód pokračuje ve smyčce. Smyčka testuje hodnotu volatile a pokračuje, pokud je true. Podmínka může být nastavena na false voláním metody "stop". Smyčka vidí false a končí, když testuje hodnotu po dokončení metody stop.

Kniha " Java Concurrency in Practice ," kterou doporučuji, dává dobré vysvětlení volatile. Tato kniha je napsána stejnou osobou, která napsala článek IBM, na který se odkazuje v otázce (ve skutečnosti cituje svou knihu na konci článku). Moje použití volatile je to, co jeho článek nazývá "příznak statusu 1".

Pokud se chcete dozvědět více o tom, jak volatile funguje pod kapotou, přečtěte si Java model paměti . Pokud chcete jít nad tuto úroveň, podívejte se na dobrou knihu architektury počítačů jako Hennessy & Patterson a přečtěte si o koherenci cache a konzistenci cache.

670
Greg Mattes

“… Volatilní modifikátor zaručuje, že každé vlákno, které čte pole, uvidí naposledy zapsanou hodnotu.”- Josh Bloch

Pokud uvažujete o použití volatile, přečtěte si balíček Java.util.concurrent který se zabývá atomovým chováním.

Příspěvek Wikipedie na Singleton Pattern ukazuje volatile v používání.

156
Ande TURNER

Důležitý bod o volatile: 

  1. Synchronizace v jazyce Java je možná pomocí klíčových slov Java synchronized a volatile a zámků.
  2. V jazyce Java nemůžeme mít proměnnou synchronized. Použití klíčového slova synchronized s proměnnou je nezákonné a bude mít za následek chybu kompilace. Namísto použití proměnné synchronized v Javě můžete použít proměnnou Java volatile, která bude instruovat vlákna JVM, aby si přečetla hodnotu proměnné volatile z hlavní paměti a lokálně ji neukládala do mezipaměti.
  3. Pokud proměnná není sdílena mezi více podprocesy, pak není nutné použít klíčové slovo volatile.

zdroj

Příklad použití volatile:

public class Singleton {
    private static volatile Singleton _instance; // volatile variable
    public static Singleton getInstance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null)
                    _instance = new Singleton();
            }
        }
        return _instance;
    }
}

Vytváříme instanci jenivě v době, kdy přichází první žádost.

Pokud nezměníme proměnnou _instancevolatile, pak vlákno, které vytváří instanci Singleton, není schopno komunikovat s jiným vláknem. Pokud tedy vlákno A vytváří instanci Singleton a těsně po vytvoření, CPU poškozuje atd., Všechna ostatní vlákna nebudou schopna vidět hodnotu _instance jako null a budou věřit, že je stále přiřazena hodnota null. 

Proč se to stalo? Protože čtenářská vlákna nedělají žádné uzamčení a dokud podproces zapisovače nevyjde ze synchronizovaného bloku, paměť nebude synchronizována a hodnota _instance nebude aktualizována v hlavní paměti. S Volatile klíčovým slovem v Javě, toto je zpracováváno jávským samotným a takové aktualizace budou viditelné všemi čtenářskými vlákny. 

Conclusion: Klíčové slovo volatile se také používá ke sdělení obsahu paměti mezi vlákny. 

Příklad použití bez volatile:

public class Singleton{    
    private static Singleton _instance;   //without volatile variable
    public static Singleton getInstance(){   
          if(_instance == null){  
              synchronized(Singleton.class){  
               if(_instance == null) _instance = new Singleton(); 
      } 
     }   
    return _instance;  
    }

Výše uvedený kód není bezpečný pro vlákna. I když znovu zkontroluje hodnotu instance v rámci synchronizovaného bloku (z důvodů výkonu), kompilátor JIT může přeskupit bajtkód tak, aby byl odkaz na instanci nastaven dříve, než bude konstruktor dokončen. To znamená, že metoda getInstance () vrací objekt, který nebyl zcela inicializován. Chcete-li kód vlákno-bezpečné, klíčové slovo volatile lze použít od Java 5 pro proměnnou instance. Proměnné, které jsou označeny jako nestálé, se zobrazí pouze ostatním vláknům, jakmile konstruktor objektu dokončí jeho úplné provedení.
Zdroj

 enter image description here

volatile použití v jazyce Java:

Iterátory s rychlou aktivací jsou typicky implementovány pomocí čítače volatile na objektu seznamu.

  • Když je seznam aktualizován, čítač se zvýší. 
  • Když je Iterator vytvořeno, aktuální hodnota čítače je vložena do objektu Iterator.
  • Když se provede operace Iterator, metoda porovná dvě hodnoty čítače a vyvolá ConcurrentModificationException, pokud se liší.

Implementace iterátorů s ochranou proti selhání je typicky lehká. Obvykle se spoléhají na vlastnosti datových struktur implementace specifického seznamu. Neexistuje žádný obecný vzor. 

95
Premraj

volatile je velmi užitečné pro zastavení vláken.

Ne, že byste měli psát vlastní témata, Java 1.6 má spoustu pěkných podprocesů. Ale pokud jste si jisti, že potřebujete vlákno, musíte vědět, jak to zastavit.

Vzor, který používám pro vlákna, je:

public class Foo extends Thread {
  private volatile boolean close = false;
  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}

Všimněte si, že není třeba synchronizace

49
Pyrolistical

Jeden běžný příklad použití volatile je použití proměnné volatile boolean jako příznak pro ukončení podprocesu. Pokud jste spustili vlákno a chcete být schopni jej bezpečně přerušit z jiného vlákna, můžete vlákno pravidelně kontrolovat příznak. Chcete-li ji zastavit, nastavte příznak na hodnotu true. Tím, že příznak volatile, můžete zajistit, že vlákno, které kontroluje, bude vidět, že bylo nastaveno při příštím kontrole, aniž by bylo nutné použít blok synchronized.

30
Dave L.

Nikdo se nezmínil o zpracování operace čtení a zápisu pro dlouhý a dvojitý typ proměnné. Čtení a zápisy jsou atomové operace pro referenční proměnné a pro většinu primitivních proměnných, s výjimkou dlouhých a dvojitých proměnných typů, které musí používat volatilní klíčové slovo jako atomové operace. @odkaz

12

Ano, volatilita musí být použita vždy, když chcete, aby k proměnné proměnné přistupovalo více vláken. Není to běžný případ, protože obvykle musíte provést více než jednu atomovou operaci (např. Zkontrolovat stav proměnné před úpravou), v takovém případě byste místo toho použili synchronizovaný blok.

12
ykaganovich

Proměnná deklarovaná klíčovým slovem volatile má dvě hlavní vlastnosti, které ji činí zvláštním.

  1. Pokud máme proměnnou volatile, nemůže být uložena do mezipaměti do mezipaměti počítače (mikroprocesorem) libovolným vláknem. Přístup vždy proběhl z hlavní paměti.

  2. Pokud existuje operacewriteprobíhající na proměnné proměnné a náhle je požadována operaceread, je zaručeno, že operacewrite bude dokončena před operací čtení.

Dvě výše uvedené vlastnosti to dokazují

  • Všechna vlákna, která čtou proměnnou volatile, budou určitě číst nejnovější hodnotu. Protože žádná hodnota v mezipaměti ji nemůže znečišťovat. A žádost o čtení bude udělena až po dokončení aktuální operace zápisu.

A na druhé straně

  • Pokud budeme dále zkoumat # 2 které jsem zmínil, můžeme vidět, že klíčové slovo volatile je ideální způsob, jak udržet sdílenou proměnnou, která má'n' počet čtených vláken a pouze jedno vlákno pro zápispro přístup. Jakmile přidáme klíčové slovo volatile, provede se. Žádná jiná režie ohledně bezpečnosti nití.

Naopak 

Mynemohupoužít klíčové slovo volatile pouze pro uspokojení sdílené proměnné, která mávíce než jedno vlákno pro zápis.

11

IMO dva důležité scénáře jiné než zastavovací vlákno, ve kterém se používá volatilní klíčové slovo 

  1. Zamykací mechanismus s dvojitou kontrolou . Používá se často ve vzorech Singleton . V tomto singleton object needs to be declared volatile.
  2. Spurious Wakeups . Vlákno se někdy může probudit z čekajícího volání, i když nebylo vydáno žádné upozornění. Toto chování se nazývá supurious wakeup. To lze zabránit pomocí podmíněné proměnné (boolean flag). Dejte volání wait () do smyčky, dokud je příznak pravdivý. Takže pokud se vlákno probudí z čekajícího volání z jiných důvodů, než je upozornění/upozornění, pak se setká s příznakem, který je stále pravdivý, a proto znovu volá. Před voláním upozornění nastavte tento příznak na hodnotu true. V tomto případě boolean flag is declared as volatile.
9
Aniket Thakur

volatile pouze zaručuje, že se zvyšují všechny podprocesy, dokonce i samotné. Například: čítač současně vidí stejnou plochu proměnné. Nepoužívá se namísto synchronizovaných nebo atomových nebo jiných, kompletně je synchronizuje. Prosím, neporovnávejte to s jinými klíčovými slovy Java. Jak ukazuje příklad, proměnné operace jsou také atomové, které selhávají nebo jsou úspěšné najednou.

package io.netty.example.telnet;

import Java.util.ArrayList;
import Java.util.List;

public class Main {

    public static volatile  int a = 0;
    public static void main(String args[]) throws InterruptedException{

        List<Thread> list = new  ArrayList<Thread>();
        for(int i = 0 ; i<11 ;i++){
            list.add(new Pojo());
        }

        for (Thread thread : list) {
            thread.start();
        }

        Thread.sleep(20000);
        System.out.println(a);
    }
}
class Pojo extends Thread{
    int a = 10001;
    public void run() {
        while(a-->0){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Main.a++;
            System.out.println("a = "+Main.a);
        }
    }
}

Dokonce i vy dáváte volatilní nebo ne výsledky budou vždy lišit. Pokud ale použijete AtomicInteger, výsledky budou vždy stejné. To platí i pro synchronizované.

    package io.netty.example.telnet;

    import Java.util.ArrayList;
    import Java.util.List;
    import Java.util.concurrent.atomic.AtomicInteger;

    public class Main {

        public static volatile  AtomicInteger a = new AtomicInteger(0);
        public static void main(String args[]) throws InterruptedException{

            List<Thread> list = new  ArrayList<Thread>();
            for(int i = 0 ; i<11 ;i++){
                list.add(new Pojo());
            }

            for (Thread thread : list) {
                thread.start();
            }

            Thread.sleep(20000);
            System.out.println(a.get());

        }
    }
    class Pojo extends Thread{
        int a = 10001;
        public void run() {
            while(a-->0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.a.incrementAndGet();
                System.out.println("a = "+Main.a);
            }
        }
    }
5
fatih tekin

Budete muset použít klíčové slovo „volatile“ nebo „synchronizované“ a jakékoli další nástroje a techniky kontroly souběžnosti, které můžete mít k dispozici, pokud vyvíjíte aplikaci s více podprocesy. Příkladem takové aplikace jsou desktopové aplikace.

Pokud vyvíjíte aplikaci, která by byla nasazena na aplikační server (Tomcat, JBoss AS, Glassfish, atd.), Nemusíte se starat o kontrolu souběžnosti sami, jak to již řešil aplikační server. Ve skutečnosti, pokud jsem si vzpomněl správně Java EE standard zakazují jakoukoliv kontrolu souběžnosti v servletech a EJB, protože je to součást vrstvy 'infrastruktury', kterou byste měli zbavit manipulace s ní. Pokud provádíte singleton objekty, můžete v takové aplikaci provádět pouze kontrolu souběžnosti. To je již vyřešeno, pokud pletete komponenty pomocí frameworku jako Spring.

Takže ve většině případů vývoje Java, kde je aplikace webovou aplikací a používající IoC framework jako Spring nebo EJB, byste nemuseli používat 'volatile'.

5
Rudi Adianto

Ano, používám to docela dost - to může být velmi užitečné pro multi-threaded kód. Článek, na který jste poukázal, je dobrý. Přestože je třeba mít na paměti dvě důležité věci:

  1. Měli byste používat volatile pouze tehdy, pokud Zcela rozumíte tomu, co dělá A jak se liší pro synchronizaci. V mnoha situacích se na povrchu objevuje těkavá , Která je jednodušší alternativou , Která je alternativou k Synchronizovanému, když je často lepší Porozumění volatile by bylo jasné, že synchronizace je jedinou volbou , která by fungovala.
  2. volatile ve skutečnosti nefunguje v dávce starších JVM, i když synchronizuje. Vzpomínám si, že jsem viděl dokument, který odkazoval na různé úrovně podpory v různých JVM, ale bohužel ho teď nemohu najít. Rozhodně se na to podívejte, pokud používáte Java pre 1.5 nebo pokud nemáte kontrolu nad JVM, na kterých bude váš program běžet.
4
MB.

Rozhodně ano. (A to nejen v Javě, ale také v C #.) Jsou chvíle, kdy potřebujete získat nebo nastavit hodnotu, která je zaručena jako atomová operace na dané platformě, například int nebo boolean, ale nevyžadují režie uzamčení závitu. Klíčové slovo volatile umožňuje zajistit, že při čtení hodnoty, kterou získáte hodnotu current a nikoli hodnotu v mezipaměti, která byla právě zastarána zápisem na jiné vlákno.

3
dgvid

Každé vlákno, které přistupuje k těkavému poli, přečte jeho aktuální hodnotu před pokračováním namísto (potenciálně) použitím hodnoty v mezipaměti.

Pouze proměnná členu může být volatilní nebo přechodná.

3
tstuber

Existují dvě různá použití nestálého klíčového slova.

  1. Zabraňuje JVM v čtení hodnot z registru (předpokládá se jako cache) a vynucuje, aby byla jeho hodnota čtena z paměti.
  2. Snižuje riziko chyb konzistence paměti.

Zabraňuje JVM v čtení hodnot v registru a vynucuje hodnotu Z paměti.

Příznak busy se používá k zabránění pokračování podprocesu v době, kdy je zařízení zaneprázdněno a příznak není chráněn zámkem:

while (busy) {
    /* do something else */
}

Testovací vlákno bude pokračovat, když jiný podproces vypne příznak busy:

busy = 0;

Vzhledem k tomu, že v testovacím vlákně je často přístupný zaneprázdněn, může JVM test optimalizovat umístěním hodnoty zaneprázdněného do registru a poté otestovat obsah registru bez čtení hodnoty obsazenosti v paměti před každým testem. Testovací podproces by nikdy zobrazit změny zaneprázdnění a jiné podproces by pouze změnit hodnotu zaneprázdněn v paměti, výsledkem zablokování. Deklarace příznaku busy jako volatile vynucuje jeho hodnotu, aby byla čtena před každým testem.

Snižuje riziko chyb konzistence paměti.

Použití volatilních proměnných snižuje riziko chyby konzistence paměti, protože zápis do proměnné volatile určuje vztah "Stane se před" s následujícími přečteními téže proměnné. To znamená, že změny proměnné volatile jsou vždy viditelné pro ostatní vlákna.

Technika čtení, psaní bez chyb konzistence paměti se nazývá atomová akce.

Atomová akce je taková, která se efektivně děje najednou. Atomová akce se nemůže zastavit uprostřed: buď se stane úplně, nebo se to vůbec nestane. Žádné vedlejší účinky atomové akce nejsou viditelné, dokud není akce dokončena.

Níže jsou uvedeny akce, které můžete určit atomově:

  • Čtení a zápisy jsou atomové pro referenční proměnné a pro většinu Primitivních proměnných (všechny typy kromě dlouhých a dvojitých).
  • Čtení a zápisy jsou atomové pro všechny proměnné deklarované volatile (Včetně dlouhých a dvojitých proměnných).

Na zdraví!

2
dheeran

Prchavé následuje.

1> Čtení a zápis volatilních proměnných různými vlákny jsou vždy z paměti, nikoli z vlastní mezipaměti vlákna nebo z registru cpu. Každý podproces se tedy vždy zabývá nejnovější hodnotou. 2> Když 2 různé podprocesy pracují v rámci haldy se stejnými instancemi nebo statickými proměnnými, lze vidět jiné akce jako mimo pořadí. Podívejte se na blog Jamese Mansona. Ale těkavé pomáhá zde.

Následující plně spuštěný kód ukazuje, jak může počet podprocesů provádět v předdefinovaném pořadí a tiskové výstupy bez použití synchronizovaného klíčového slova.

thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3

K dosažení tohoto cíle můžeme použít následující plnohodnotný běžící kód.

public class Solution {
    static volatile int counter = 0;
    static int print = 0;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread[] ths = new Thread[4];
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new Thread(new MyRunnable(i, ths.length));
            ths[i].start();
        }
    }
    static class MyRunnable implements Runnable {
        final int thID;
        final int total;
        public MyRunnable(int id, int total) {
            thID = id;
            this.total = total;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                if (thID == counter) {
                    System.out.println("thread " + thID + " prints " + print);
                    print++;
                    if (print == total)
                        print = 0;
                    counter++;
                    if (counter == total)
                        counter = 0;
                } else {
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        // log it
                    }
                }
            }
        }
    }
}

Následující odkaz github má readme, který dává správné vysvětlení. https://github.com/sankar4git/volatile_thread_ordering

2
sankar banerjee

Volatilní proměnné jsou synchronizace s nízkou hmotností. Když je viditelnost nejnovějších dat mezi všemi vlákny požadavek a atomicita může být ohrožena, v takových situacích musí být preferovány volatilní proměnné. Čtení proměnných proměnných vždy vrátí nejnovější zápis provedený libovolným vláknem, protože nejsou uloženy v mezipaměti v registrech ani v mezipaměti, kde ostatní procesory nevidí. Volatile je Lock-Free. Používám volatile, když scénář splňuje kritéria uvedená výše. 

2
Neha Vari

Z dokumentace Oracle page , vzniká potřeba volatilní proměnné k opravě problémů s konzistencí paměti:

Použití volatilních proměnných snižuje riziko chyb konzistence paměti, protože jakýkoli zápis do proměnné volatile určuje vztah předcházející události s následujícími čteními téže proměnné. 

To znamená, že změny proměnné volatile jsou vždy viditelné pro ostatní vlákna. To také znamená, že když vlákno přečte proměnnou proměnnou, nevidí pouze poslední změnu volatile, ale také vedlejší účinky kódu, který změnu vedl.

Jak je vysvětleno v odpovědi Peter Parker, v nepřítomnosti modifikátoru volatile může mít každý svazek vláken vlastní kopii proměnné. Vytvořením proměnné jako volatile byly opraveny problémy s konzistencí paměti. 

Pro lepší pochopení se podívejte na stránku jenkov tutorial. 

Podívejte se na příslušnou otázku týkající se SE, kde naleznete další informace o volatile a použití případů volatile:

Rozdíl mezi volatilitou a synchronizací v jazyce Java

Jeden praktický případ použití:

Máte mnoho podprocesů, které potřebují tisknout aktuální čas v určitém formátu, například: Java.text.SimpleDateFormat("HH-mm-ss"). Yon může mít jednu třídu, která převádí aktuální čas na SimpleDateFormat a aktualizuje proměnnou na každou sekundu. Všechny ostatní podprocesy mohou jednoduše použít tuto proměnnou proměnné k tisku aktuálního času v souborech protokolu. 

1
Ravindra babu

Níže je uveden velmi jednoduchý kód, který demonstruje požadavek volatile.

// Code to prove importance of 'volatile' when state of one thread is being mutated from another thread.
// Try running this class with and without 'volatile' for 'state' property of Task class.
public class VolatileTest {
    public static void main(String[] a) throws Exception {
        Task task = new Task();
        new Thread(task).start();

        Thread.sleep(500);
        long stoppedOn = System.nanoTime();

        task.stop(); // -----> do this to stop the thread

        System.out.println("Stopping on: " + stoppedOn);
    }
}

class Task implements Runnable {
    // Try running with and without 'volatile' here
    private volatile boolean state = true;
    private int i = 0;

    public void stop() {
        state = false;
    } 

    @Override
    public void run() {
        while(state) {
            i++;
        }
        System.out.println(i + "> Stopped on: " + System.nanoTime());
    }
}

Když volatile není použito: nikdy se nezobrazí zpráva 'Stopped on: xxx' ani po 'Stopping on: xxx' a program bude pokračovat v běhu.

Stopping on: 1895303906650500

Když je volatile použito: okamžitě uvidíte 'Stopped on: xxx'.

Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300
0
manikanta

Při použití s ​​proměnnou bude volatile klíč, který zajistí, že vlákna čtení této proměnné uvidí stejnou hodnotu. Pokud nyní máte více proměnných, které čtou a zapisují do proměnné, nebude proměnná volatile dostatečná a data budou poškozena. Obrazová vlákna čtou stejnou hodnotu, ale každá z nich udělala nějaké chages (např. Přírůstek čítače), při zápisu zpět do paměti je porušena integrita dat. To je důvod, proč je nutné, aby byly variabilní synchronizované (různé způsoby možné).

Pokud jsou změny provedeny 1 vláknem a ostatní potřebují pouze tuto hodnotu přečíst, bude vhodná volatilita.

0
Java Main

A Volatile proměnná je asynchronně modifikována současným spuštěním vláken v aplikaci Java. Není dovoleno mít lokální kopii proměnné, která se liší od hodnoty, která je aktuálně uložena v "hlavní" paměti. Proměnná deklarovaná volatile musí mít své údaje synchronizované napříč všemi vlákny, takže při každém přístupu nebo aktualizaci proměnné v libovolném vlákně budou všechny ostatní vlákna okamžitě vidět stejnou hodnotu. Pravděpodobně je pravděpodobné, že volatilní proměnné mají vyšší přístup a aktualizují režii než „prosté“ proměnné, protože důvodem, proč mohou mít vlákna vlastní kopii dat, je lepší efektivita.

Když je pole deklarováno jako nestálé, kompilátor a runtime jsou upozorněny, že tato proměnná je sdílena a že operace na ní by neměly být přeskupeny s jinými operacemi paměti.Volatilní proměnné nejsou uloženy v mezipaměti v registrech nebo v mezipaměti, kde jsou skryty před jinými procesory, takže čtení proměnné proměnné vždy vrátí poslední zápis libovolným vláknem.

odkazujeme zde http://techno-terminal.blogspot.in/2015/11/what-are-volatile-variables.html

0
satish

proměnná volatile se v podstatě používá pro okamžitou aktualizaci (flush) v hlavní sdílené vyrovnávací paměti, jakmile se aktualizuje, takže změny se okamžitě projeví u všech pracovních vláken.

0
Niyaz Ahamad

Mám rád Jenkovovo vysvětlení :

Klíčové slovo Java volatile se používá k označení proměnné Java jako "uloženo v hlavní paměti". Přesněji řečeno, znamená to, že každé čtení proměnné proměnné bude čteno z hlavní paměti počítače a nikoli z mezipaměti CPU a že každý zápis do proměnné proměnné bude zapisován do hlavní paměti, a nikoli pouze do mezipaměti CPU .

Vlastně, protože Java 5, volatilní klíčové slovo zaručuje více než jen to, že Volatilní proměnné jsou zapisovány a čteny z hlavní paměti. 

Jedná se o prodlouženou záruku za viditelnost, tzv. Záruku.

Úvahy o výkonu volatile

Čtení a zápis volatilních proměnných způsobí čtení nebo zápis proměnné do hlavní paměti. Čtení a zapisování do hlavní paměti je dražší než přístup k mezipaměti CPU. Přístup k nestálým proměnným také zabraňuje přeskupování instrukcí, což je běžná technika vylepšení výkonu. Měli byste tedy používat pouze proměnné proměnné, když skutečně potřebujete vynutit viditelnost proměnných.

0
yoAlex5