Frage

Bei der Arbeit heute, stieß ich auf das volatile Schlüsselwort in Java. Nicht sehr vertraut mit ihm zu sein, fand ich diese Erklärung:

  

Java Theorie und Praxis: Verwalten Volatilität

das Detail, in denen dieser Artikel das Stichwort in Frage erklärt, verwenden Sie jemals oder könnten Sie jemals einen Fall sehen, in dem Sie dieses Schlüsselwort in der richtigen Art und Weise verwenden könnten?

War es hilfreich?

Lösung

volatile hat Semantik für Speicher Sichtbarkeit. Grundsätzlich wird der Wert eines volatile Feld sichtbar für alle Leser (andere Threads im Besonderen) nach einer Schreiboperation abgeschlossen ist darauf. Ohne volatile Leser könnte etwas nicht aktualisierten Wert sehen.

Um Ihre Frage zu beantworten: Ja, ich verwende eine volatile Variable zu steuern, ob ein Code eine Schleife fortgesetzt. Die Schleife prüft die volatile Wert und setzt, wenn es true wird. Der Zustand kann eingestellt werden durch den Aufruf einer „stop“ -Methode false. Die Schleife sieht false und endet, wenn es den Wert testet, nachdem die Stop-Methode der Ausführung beendet.

Das Buch " Java Concurrency in Practice ", die ich gibt sehr empfehlen, eine gute Erklärung von volatile. Dieses Buch wird von derselben Person geschrieben, die die IBM Artikel schrieben, die in der Frage verwiesen wird (in der Tat, zitiert er sein Buch auf der Unterseite dieses Artikels). Meine Verwendung von volatile ist, was sein Artikel nennt den „Muster-1-Status-Flag.“

Wenn Sie mehr erfahren möchten, wie volatile unter der Haube arbeitet, lesen Sie auf das Java-Speichermodell . Wenn Sie darüber hinaus, dass Level gehen wollen, überprüfen Sie ein gutes Computer-Architektur Buch aus wie Hennessy & Patterson und lesen Sie über die Cache-Kohärenz und Cache-Konsistenz.

Andere Tipps

„... die flüchtigen Modifikator garantiert, dass jeder Thread, der ein Feld liest, wird die zuletzt geschriebenen Wert sehen.“ - Josh Bloch
Wenn Sie über die Verwendung von volatile denken, lesen Sie auf der Verpackung nach oben java.util.concurrent , die mit Atom-Verhalten befasst.
Die Wikipedia-Post auf einem Singleton Pattern im Einsatz flüchtiger zeigt.

Wichtiger Punkt über volatile:

  1. Synchronisation in Java ist möglich durch die Verwendung von Java Schlüsselwörter synchronized und volatile und Schlösser.
  2. In Java können wir synchronized Variable nicht haben. Mit synchronized Schlüsselwort mit einer Variablen ist illegal und wird in Kompilierungsfehler. Statt in Java die synchronized Variable verwenden, können Sie den Java-volatile Variable verwenden, die JVM-Threads anweisen, den Wert von volatile Variable aus dem Hauptspeicher und nicht zwischenspeichern es lokal zu lesen.
  3. Wenn eine Variable nicht zwischen mehreren Threads gemeinsam genutzt wird, dann gibt es keine Notwendigkeit, das volatile Schlüsselwort zu verwenden.

Quelle

Beispiel für die Verwendung von 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;
    }
}

Wir Beispiel träge zum Zeitpunkt der ersten Anfrage kommt erstellen.

Wenn wir nicht die _instance Variable volatile machen dann die Themen, das die Instanz von Singleton schafft ist nicht in der Lage zu dem anderen Thread zu kommunizieren. Also, wenn Thread A schafft Singleton-Instanz und nur nach der Erstellung, die CPU korrumpiert usw., alle anderen Threads nicht in der Lage sein, den Wert von _instance als nicht null, um zu sehen, und sie werden es glauben immer noch null zugeordnet ist.

Warum geschieht das? Da reader Gewinde sind keine Verriegelungs tun, und bis der Faden writer aus einem synchronisierten Block kommt, wird der Speicher nicht synchronisiert werden, und den Wert des _instance wird nicht im Hauptspeicher aktualisiert werden. Mit dem flüchtigen Schlüsselwort in Java wird dies durch Java behandelt selbst und solche Updates werden von allen Leser-Threads sichtbar sein.

  

Fazit : volatile Schlüsselwort auch den Inhalt des Speichers zwischen Threads verwendet wird, zu kommunizieren.

Beispiel für die Verwendung von ohne flüchtig:

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;  
    }

Der obige Code ist nicht Thread-sicher. Obwohl sie den Wert der Instanz wieder im synchronisierten Block (aus Leistungsgründen) prüft, kann der JIT-Compiler den Bytecode in einer Weise neu anordnen, dass der Verweis auf die Instanz festgelegt wird, bevor der Konstruktor seine Ausführung beendet hat. Das heißt, das Verfahren getInstance () gibt ein Objekt, das nicht vollständig initialisiert worden ist. Um den Code Thread-sicher zu machen, das Schlüsselwort volatile kann, da Java 5 für das Instanz-Variable verwendet werden. Variablen, die als flüchtiges markiert bekommt nur sichtbar für andere Threads, wenn der Konstruktor des Objekts seiner Ausführung vollständig abgeschlossen ist.
Quelle

 image description hier

volatile Verwendung in Java :

Die fehler schnell Iteratoren sind Regel implementiert einen volatile Zähler auf der Liste Objekt verwenden.

  • Wenn die Liste aktualisiert wird, wird der Zähler erhöht.
  • Wenn ein Iterator erstellt wird, wird der aktuelle Wert des Zählers in dem Iterator Objekt eingebettet ist.
  • Wenn ein Iterator Operation durchgeführt wird, vergleicht das Verfahren die zwei Zählerwerte, und wirft einen ConcurrentModificationException wenn sie unterschiedlich sind.

Die Umsetzung der Failsafe-Iteratoren ist in der Regel leicht. Sie stützen sich typischerweise auf die Eigenschaften der spezifischen Datenstrukturen der Liste Implementierung. Es gibt keine allgemeinen Muster.

volatile sehr nützlich Threads zu beenden.

Nicht, dass Sie Ihre eigenen Threads schreiben sollte, Java 1.6 hat viele schöne Thread-Pools. Aber wenn Sie sicher sind, benötigen Sie einen Thread, Sie müssen wissen, wie es zu stoppen.

Das Muster, das ich für Threads verwenden ist:

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
  }
}

Beachten Sie, wie es gibt keine Notwendigkeit für die Synchronisation

Ein allgemeines Beispiel für die Verwendung von volatile ist es, eine variable volatile boolean als Flag zu verwenden, um einen Thread zu beenden. Wenn Sie einen Thread gestartet haben, und Sie wollen in der Lage sein, ohne Schwierigkeiten aus einem anderen Thread unterbrechen, können Sie sich das Gewinde in regelmäßigen Abständen eine Flagge überprüfen. Um ihn zu stoppen, setzen Sie das Flag auf true. Indem die Flagge volatile können Sie sicherstellen, dass der Thread, es wird überprüft werden sehen, es das nächste Mal gesetzt wurde, es überprüft er, ohne auch nur einen synchronized Block verwenden zu dürfen.

Eine Variable mit volatile Schlüsselwort deklariert, hat zwei Hauptqualitäten, die es besonders machen.

  1. Wenn wir eine flüchtige Variable haben, kann es nicht in den von jedem Thread (Mikroprozessor) Cache-Speicher des Computers zwischengespeichert werden. Zugriff immer geschah aus dem Hauptspeicher.

  2. Wenn es eine Schreiboperation auf einem flüchtigen Variable gehen, und plötzlich ein Lesevorgang angefordert wird, wird sichergestellt, dass die Schreibvorgang vor dem Lesevorgang beendet wird, .

Zwei oben genannten Eigenschaften ableiten, dass

  • die Fäden alles eine flüchtige Variable lesen, wird den neuesten Wert auf jeden Fall lesen. Da kein Cache gespeicherten Wert kann es verschmutzen. Und auch die Leseanforderung erst nach Abschluss der aktuellen Schreiboperation gewährt werden.

Und auf der anderen Seite,

  • Wenn wir weiter die # untersuchen 2 , dass ich erwähnt habe, können wir das volatile Schlüsselwort ist ein idealer Weg, sehen eine gemeinsame Variable zu halten, die hat ‚n‘ Anzahl der lesen Fäden und nur ein Schreib Thread , darauf zuzugreifen. Sobald wir das volatile Schlüsselwort hinzufügen, wird es getan. Keine andere Kopf über Thread-Sicherheit.

Conversly,

Wir nicht Verwendung von volatile Stichwort machen, nur eine gemeinsame Variable zu erfüllen, die hat mehr als ein Schreib Threads es Zugriff .

Ja, volatile verwendet werden muss, wann immer Sie wollen eine veränderbare Variable von mehreren Threads zugegriffen werden. Es ist nicht sehr verbreitet usecase weil in der Regel müssen Sie mehr als eine einzige atomare Operation durchführen (z überprüfen Sie die Variable Zustand, bevor es zu ändern), in dem Fall, dass Sie stattdessen einen synchronisierten Block verwenden würde.

Niemand hat die Behandlung von Lese erwähnt und Schreiboperation für lange und Doppelvariablentyp. Liest und schreibt sind atomare Operationen für Referenzvariablen und für die meisten primitiven Variablen, mit Ausnahme von langen und Doppelvariablentypen, die die flüchtigen Schlüsselwort verwenden müssen atomare Operationen sein. @link

Meiner Meinung nach, zwei wichtigen Szenarien andere als Fadenstopp in der flüchtigen Schlüsselwort verwendet wird, sind:

  1. doppelt geprüft Mechanismus sperren. Häufig in Singleton Design Muster. Dabei wird der muss Singleton-Objekt werden, um flüchtige erklärt .
  2. Unechte Wakeups . Thread kann manchmal bis von Warte Anruf wecken, auch wenn kein benachrichtigen Anruf ausgegeben wurde. Dieses Verhalten wird supurious Wakeup genannt. Dies kann durch die Verwendung einer Bedingungsvariable (boolean flag) begegnet werden. Setzen Sie den wait () -Aufruf in einer while-Schleife, solange das Flag wahr ist. Also, wenn Thread von Warte Anruf aufwacht aus irgendwelchen Gründen, die nicht benachrichtigen / notifyAll dann trifft es Flag immer noch wahr ist und daher warten Anrufe wieder. Vor dem Aufruf dieses Flag auf true notify gesetzt. In diesem Fall wird der boolean-Flag wird als flüchtig erklärt .

Sie müssen ‚volatile‘ Schlüsselwort verwenden, oder ‚synchronisiert‘ und alle anderen Concurrency Control Tools und Techniken, die Sie zur Verfügung haben könnte, wenn Sie eine Multithread-Anwendung entwickeln. Beispiel für eine solche Anwendung ist Desktop-Anwendungen.

Wenn Sie eine Anwendung entwickeln, die auf Anwendungsserver bereitgestellt werden würde (Tomcat, JBoss AS, Glassfish, etc) Sie müssen Nebenläufigkeitssteuerung nicht selbst behandeln, da sie bereits durch den Anwendungsserver adressiert. In der Tat erinnerte, wenn ich den Java EE-Standard korrekt jede Nebenläufigkeitssteuerung in Servlets und EJBs verbieten, da sie Teil der ‚Infrastruktur‘ Schicht, die Sie beim Umgang mit ihm befreit werden sollen. Sie tun nur Concurrency Control in einer solchen App, wenn Sie Singleton Objekte sind implementiert. Dies auch schon angesprochen, wenn Sie Ihre Komponenten frameworkd wie Spring stricken.

Also, in den meisten Fällen von der Java-Entwicklung, wo die Anwendung eine Web-Anwendung ist und mit IoC-Framework wie Spring oder EJB, würden Sie nicht brauchen ‚volatile‘ zu verwenden.

volatile garantiert nur, dass alle Fäden, auch selbst sind erhöht wird. Zum Beispiel: ein Zähler sieht dieselbe Seite der variablen zugleich. Es ist nicht statt synchronisiert oder atomare oder andere Sachen, es vollständig macht die Lesevorgänge synchronisiert verwendet. Bitte vergleichen Sie es nicht mit anderen Java-Keywords. Wie das folgende Beispiel flüchtige Variable Operationen zeigt auch atomare sie scheitern oder sofort Erfolg haben.

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);
        }
    }
}

Auch setzen Sie flüchtig oder nicht Ergebnisse werden immer unterscheiden. Aber wenn Sie Atomicinteger wie unten Ergebnis zu erzielen, wird immer gleich. Dies ist das gleiche mit synchronisiertem auch.

    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);
            }
        }
    }

Ja, ich benutze es ziemlich viel - es kann für Multi-Threaded-Code sehr nützlich sein. Der Artikel, den Sie zeigte auf, ist gut. Zwar gibt es zwei wichtige Dinge zu beachten:

  1. Sie sollten nur flüchtig, wenn Sie vollständig zu verstehen, was es tut und wie es sich zu synchronisiert. In vielen Situationen flüchtig erscheint, auf der Oberfläche, ein einfacher mehr zu sein performante Alternative zu synchronisiert, wenn oft ein besserer Verständnis von flüchtigen würde klar, dass synchronisiert ist der einzige Option, die funktionieren würde.
  2. flüchtig nicht wirklich in einem Werk Viele ältere JVMs, obwohl synchronisiert hat. Ich erinnere mich an ein Dokument zu sehen, dass die verschiedenen Ebenen der Unterstützung in verschiedenen JVMs referenzierten aber leider kann ich es jetzt nicht finden. Auf jeden Fall in sie aussehen, wenn Sie verwenden Java Pre 1.5 oder wenn Sie nicht die Kontrolle über die JVMs, die Ihr Programm wird ausgeführt wird.

Absolut, ja. (Und das nicht nur in Java, sondern auch in C #). Es gibt Zeiten, wenn Sie erhalten müssen oder einen Wert eingestellt, der eine atomare Operation sein auf bestimmte Plattform garantiert ist, ein int oder boolean, zum Beispiel, aber nicht erforderlich der Aufwand für Gewindesicherung. Das flüchtige Schlüsselwort können Sie sicherstellen, dass, wenn Sie den Wert lesen, dass Sie die Strom Wert und nicht einen zwischengespeicherten Wert zu erhalten, die nur durch einen Schreib auf einem anderen Thread obsolet gemacht wurde.

Jeder Thread ein flüchtiges Feld Zugriff auf ihren gegenwärtigen Wert, bevor Sie fortfahren, statt (potentiell) mit einem Cache gespeicherten Wert lesen.

Nur Membervariable kann flüchtig oder vorübergehend sein.

Es gibt zwei verschiedene Verwendungen von flüchtigem Schlüsselwort.

  1. Verhindert JVM von Werten aus dem Register zu lesen (unter der Annahme als Cache) und zwingt sein Wert aus dem Speicher gelesen werden.
  2. Reduziert das Risiko von Speicher in-Konsistenzfehler.
  

Verhindert, dass JVM von Werten in dem Register zu lesen, und zwingt seine   Wert aus dem Speicher gelesen werden.

A Besetzt-Flag verwendet wird, einen Thread zu verhindern, dass weiterhin, während das Gerät beschäftigt ist und das Flag wird nicht durch eine Sperre geschützt:

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

Der Test Thread wird fortgesetzt, wenn ein anderer Thread der Busy-Flag schaltet sich aus, :

busy = 0;

Da jedoch beschäftigte häufig in dem Test Thread zugegriffen wird, kann die JVM den Test optimieren, indem den Wert des Besetzt in einem Register platziert, dann den Inhalt des Registers testen, ohne vor jedem Test den Wert des Besetzt im Speicher zu lesen. Der Test Thread würde nie beschäftigt Veränderung sehen und der andere Thread würde nur den Wert beschäftigt im Speicher ändern, was in einer Sackgasse. Deklarieren des Besetzt-Flag als flüchtige Kräfte ihr Wert vor jedem Test gelesen werden.

  

Reduziert das Risiko von Speicherkonsistenzfehler.

Mit flüchtigen Variablen reduziert das Risiko von Speicherkonsistenzfehler , da jeder Schreibvorgang in eine volatile Variable a etabliert „passiert-vor“ Beziehung mit anschließendem liest die gleichen Variablen. Das bedeutet, dass Änderungen an einer flüchtigen Variable sind immer sichtbar für andere Themen.

Die Technik des Lesens, Schreibens ohne Speicherkonsistenzfehler genannt wird Atom-Aktion .

Eine atomare Aktion ist eine, die effektiv auf einmal passiert. Eine atomare Aktion kann in der Mitte nicht stoppen: es entweder vollständig geschieht, oder es gar nicht passieren. Keine Nebenwirkungen einer atomaren Aktion sind sichtbar, bis die Aktion abgeschlossen ist.

Im Folgenden sind Aktionen, die Sie angeben können, die atomar sind:

  • Liest und schreibt atomar sind für Referenzvariablen und für die meisten primitive Variablen (alle Typen außer lang und doppelt).
  • Liest und schreibt atomar sind für alle Variablen deklariert volatile (Einschließlich lange und Doppel Variablen).

Cheers!

Flüchtige Variablen sind leichte Synchronisation. Wenn Sichtbarkeit der aktuellen Daten von allen Threads Anforderung und Unteilbarkeit ist zu können, müssen bevorzugt werden flüchtige Variablen in solchen Situationen beeinträchtigt werden. Lesen Sie auf flüchtige Variablen immer wieder zurückkehren letzten Schreib von jedem Thread getan, da sie weder in den Registern zwischengespeichert werden noch in Caches, wo andere Prozessoren nicht sehen können. Flüchtige ist Lock-Free. Ich benutze flüchtig, wenn Szenario Kriterien erfüllt, wie oben erwähnt.

Volatile hat folgende.

1> Lesen und Schreiben von flüchtigen Variablen durch verschiedene Threads sind immer aus dem Gedächtnis, nicht aus Thread eigenen Cache oder CPU-Register. Also jeder Thread, immer beginnend mit dem letzten Wert. 2> Wenn zwei verschiedene Threads mit derselben Instanz oder statischen Variablen in Haufen arbeiten, kann man andere Aktionen wie in der falschen Reihenfolge sehen. Siehe jeremy Mansons Blog zu diesem Thema. Aber flüchtige hilft hier.

läuft vollständig folgenden Code zeigt, wie eine Anzahl von Threads in einer festgelegten Reihenfolge und Druckausgaben ohne Verwendung synchronisierter Schlüsselwort ausführen kann.

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

Um dies zu erreichen wir folgenden vollwertiges Lauf Code verwenden können.

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
                    }
                }
            }
        }
    }
}

Die folgende Github Link hat eine Readme, die richtige Erklärung gibt. https://github.com/sankar4git/volatile_thread_ordering

Von der Oracle-Dokumentation , die Notwendigkeit für volatile Variable stellt Speicherkonsistenzprobleme zu beheben:

  

flüchtige Variablen verwenden, verringert das Risiko von Speicherkonsistenzfehler, da jeder Schreibvorgang in eine volatilen Variable stellt ein geschieht zuvor Beziehung mit anschließendem dem gleichen Variable liest.

Das bedeutet, dass Änderungen an einer volatile Variable auf andere Threads immer sichtbar sind. Es bedeutet auch, dass, wenn ein Thread eine flüchtige Variable liest, ist es nicht nur die letzte Änderung der volatile, sondern auch die Nebenwirkungen des Codes sieht, der die Änderung führte.

Wie in Peter Parker Antwort erklärt, in Abwesenheit von volatile Modifikator, jeder Stapel des Threads kann ihre eigene Kopie der Variablen hat. Indem die Variable als volatile, Speicherkonsistenzprobleme behoben wurden.

Hier finden Sie aktuelle jenkov Tutorial-Seite für ein besseres Verständnis.

Hier finden Sie aktuelle verwandte SE Frage für einige weitere Details zu den flüchtigen & Anwendungsfälle flüchtigen zu verwenden:

Unterschied zwischen flüchtigen und synchronisiert in Java

Ein praktischer Anwendungsfall:

Sie haben viele Threads, die aktuelle Uhrzeit in einem bestimmten Format zum Beispiel drucken müssen: java.text.SimpleDateFormat("HH-mm-ss"). Yon kann eine Klasse hat, die aktuelle Zeit in SimpleDateFormat umwandelt und die Variable für jede Sekunde aktualisiert. Alle andere Threads können einfach verwenden diese flüchtigen Variable aktuelle Zeit in Log-Dateien zu drucken.

A Volatile variable asynchron modifiziert durch gleichzeitige Threads in einer Java-Anwendung ausgeführt wird. Es ist nicht eine lokale Kopie einer Variablen zu haben, erlaubt, die derzeit in „main“ Speicher gehalten von dem Wert unterscheidet. Effektiv erklärt eine Variable volatile muss seine Daten über alle Threads synchronisiert haben, so dass, wenn Sie die Variable in jedem Thread zuzugreifen oder aktualisieren, alle anderen Threads sofort den gleichen Wert sehen. Natürlich ist es wahrscheinlich, dass flüchtige Variablen einen höheren Zugriff und Update-Overhead als „plain“ Variablen haben, da die Grund-Threads ihre eigene Kopie der Daten für eine bessere Effizienz haben können.

Wenn ein Feld volatile deklariert wird, der Compiler und Laufzeit werden darüber in Kenntnis gesetzt, dass dieser Variable gemeinsam genutzt wird und dass Operationen auf sie nicht mit anderen Speichern operations.Volatile Variablen neu geordnet werden sollen, werden in Registern oder in Caches nicht im Cache gespeichert, wo sie sind versteckt von anderen Prozessoren, so dass ein Lese einer flüchtigen Variable gibt immer den neuesten Schreib von jedem Thread.

Referenz finden diese http: // Techno -terminal.blogspot.in/2015/11/what-are-volatile-variables.html

Der flüchtige Schlüssel, wenn sie mit einer Variablen verwendet wird, stellen Sie sicher, dass Threads diese Variable liest den gleichen Wert sehen. Nun, wenn Sie mehrere Threads das Lesen und Schreiben auf eine Variable, so dass die Variable volatile wird nicht genug und Daten werden beschädigt haben. Bild Threads denselben Wert gelesen haben, aber jeder hat einige chages getan (zB erhöht einen Zähler), wenn wieder in den Speicher zu schreiben, die Datenintegrität verletzt. Deshalb ist es notwendig, die varible synchronisiert zu machen (diffrent Wege sind möglich)

Wenn die Änderungen von 1 Faden fertig sind und die anderen müssen nur diesen Wert lesen, wird der flüchtige geeignet sein.

Ich mag Jenkov Erklärung :

  

Die Java volatile Schlüsselwort verwendet wird, ein Java-Variable zu markieren als "im Hauptspeicher gespeichert werden". Genauer gesagt bedeutet das, dass wird jede Lese eines flüchtigen Variable aus dem Hauptspeicher des Computers gelesen werden, und nicht von dem CPU-Cache, und dass jeder zu einem flüchtigen Variable schreiben wird in dem Hauptspeicher geschrieben werden, und nicht nur auf die CPU-Cache .

     

Eigentlich seit Java 5 das Schlüsselwort volatile garantiert mehr als nur das   flüchtige Variablen werden geschrieben und aus dem Hauptspeicher gelesen.

Es wird längere Sicht garantiert so genannte passiert-vor-Garantie.

  

Überlegungen zur Leistung von flüchtigem

     

Lesen und Schreiben von flüchtigen Variablen wird auf die Variable in den Hauptspeicher gelesen oder geschrieben werden. Lesen und in dem Hauptspeicher zu schreiben ist teurer als die CPU-Cache zugreifen. Zugriff auf flüchtige Variablen auch verhindern, dass Anweisung Umordnung, die eine normale Leistungssteigerung Technik ist. Daher sollten Sie nur flüchtige Variablen verwenden, wenn Sie wirklich die Sichtbarkeit von Variablen müssen erzwingen.

volatile Variable ist grundsätzlich für sofortige Aktualisierung verwendet (flush) in Haupt gemeinsam genutzten Cache-Zeile, sobald sie aktualisiert, so dass Änderungen an alle Arbeitsthreads reflektierten sofort.

Hier ist ein sehr einfacher Code, um die Anforderung von volatile für Variable zu zeigen, die die Thread-Ausführung von anderen Threads zu steuern, verwendet wird (dies ist ein Szenario, in der volatile erforderlich).

// 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());
    }
}

Wenn volatile nicht verwendet wird: Sie nie sehen ' Gestoppt auf: xxx ' Nachricht auch nach ' Anhalten auf: xxx ' und das Programm läuft weiter.

Stopping on: 1895303906650500

Wenn volatile verwendet: Sie werden sehen, die ' Gestoppt auf: xxx .' Sofort

Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300

Demo: https://repl.it/repls/SilverAgonizingObjectcode

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top