IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Mot clé Volatile


Sujet :

Langage Java

  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Directeur technique
    Inscrit en
    Octobre 2011
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 1
    Par défaut Mot clé Volatile
    Bonjour à tous,

    J'ai un petit souci avec le mot clef Volatile.
    Pour le compte d'une formation, j'ai essayé d'illustrer l'utilité de cette déclaration par l'exemple ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class MyThread extends Thread {
     
     
    	private boolean m_boucle = true;
     
    	public void stopTheJob() {
    		m_boucle = false;
    	}
     
    	/** 
             * {@inheritDoc}
             */
    	@Override
    	public void run() {
    		super.run();
    		while (m_boucle) {
    			System.out.print('.');
    		}		
    	}
    }

    Un thread à l'extérieur évidemment change la valeur de m_boucle, mais avec ou SANS volatile, la boucle s'arrête toujours.
    Je suis en Java 5

    Merci d'avance.

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Le comportement de volatile n'est pas facile à montrer, car selon les optimisations de la JVM "ça peut" marcher même sans volatile...


    a++

  3. #3
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 661
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 661
    Par défaut
    bonjour,

    je suis surpris de voir super.run() dans la méthode run() de la classe. Est-ce une faute ? Sinon quel en serait l'intérêt ?


    ma question est sans doute hors sujet, si c'est le cas je suis désolé, mais ce super.run() m'intrigue

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par Auteur Voir le message
    Est-ce une faute ? Sinon quel en serait l'intérêt ?
    Probablement! Aucun!

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Cela peut être intéressant pour mettre en place une instanciation de singleton thread-safe

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    public class Singleton{
        private volatile static Singleton instance;
        private Singleton(){}
     
        public static Singleton getInstance() {
           if(instance == null){
              synchronized(Singleton.class){
                 if(instance == null){
                    instance = new Singleton();
                 }
              }
           }
     
            return instance;
        }
    }

    ça ne marche que sur du java 1.5 minimum car volatile est mal géré en dessous

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par Yo Eight Voir le message
    Cela peut être intéressant pour mettre en place une instanciation de singleton thread-safe
    Non, comme indiqué dans le lien ci dessous, ce pattern ne fonctionne pas

    http://christophej.developpez.com/tu...tithread/#L3.4

    pour faire court, avec ce pattern, un autre thread pourrait voir "instance" alors que le constructeur n'a pas fini de s'initialiser.


    Pour les singleton, la deux seules pattern recommandables sont
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public class Singleton {
    private Singleton instance = new Singleton();
    public Singleton getInstance() {return instance;}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class Singleton {
    private Singleton instance;
    public synchronized Singleton getInstance() {
      if (instance ==null)
          instance = new Singleton();
      return instance;
    }

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Il a bien précisé, "que sur du Java 1.5 minimum."
    Ce même article indique que dans ce cas, la lecture/écriture des variables volatiles n'a pas le droit d'être réorganisée, ce qui donc empêche de voir une instance à moitié construite avec cette instruction.

    Personnellement, j'ai une confiance toute relative dans le respect de cette contrainte par les autres JVMs, et je préfère synchroniser. (Et, autant que possible, initialiser au chargement.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Non, comme indiqué dans le lien ci dessous, ce pattern ne fonctionne pas

    http://christophej.developpez.com/tu...tithread/#L3.4
    Dommage que vous ayez lu trop rapidement mon post (j'ai bien précisez la version de la JVM). Malheureusement vos exemples ne sont pas performant car vous synchronisez continuellement l'obtention de l'instance alors que ce n'est plus nécessaire après qu'elle a été créée. Dans votre premier exemple, vous instanciez inutilement l'objet, ce qui peut ralentir le démarrage de votre application si sa construction nécessite des opérations lourdes.

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Citation Envoyé par Yo Eight Voir le message
    Dommage que vous ayez lu trop rapidement mon post (j'ai bien précisez la version de la JVM).
    Ouaip. Rappelé dans mon propre message au-dessus.

    Citation Envoyé par Yo Eight Voir le message
    Malheureusement vos exemples ne sont pas performant car vous synchronisez continuellement l'obtention de l'instance alors que ce n'est plus nécessaire après qu'elle a été créée.
    Vérifier sans arrêt la valeur d'une variable volatile n'est pas forcément mieux en termes de performances, les caches prennent cher, et une synchro peut souvent être assurée pour le même prix. Tu as mesuré ce que ça donne en conditions réelles ? Ton argument, bien que potentiellement valable en théorie dans certains cas, ne me semble pas spécialement pertinent dans le monde réél.

    Citation Envoyé par Yo Eight Voir le message
    Dans votre premier exemple, vous instanciez inutilement l'objet, ce qui peut ralentir le démarrage de votre application si sa construction nécessite des opérations lourdes.
    Ce n'est pas forcément dans ce sens-là que c'est préférable. Souvent, il vaut mieux prendre le temps de le faire au début que de ralentir une exécution normale plus tard. Après, tout dépend de quel genre d'application il s'agit, et de ce qui décide si oui ou non l'instance va être utilisée.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Citation Envoyé par thelvin Voir le message

    Vérifier sans arrêt la valeur d'une variable volatile n'est pas forcément mieux en termes de performances, les caches prennent cher, et une synchro peut souvent être assurée pour le même prix. Tu as mesuré ce que ça donne en conditions réelles ? Ton argument, bien que potentiellement valable en théorie dans certains cas, ne me semble pas spécialement pertinent dans le monde réél.
    Je ne pose pas du code sur un forum, sans en vérifier un minimum la véracité. Pour appuyer mes dires voici un site qui en parle http://www.javaperformancetuning.com/news/qotm051.shtml

    volatile ne sera dans n'importe quelle situation jamais plus couteux qu'un synchronized. au pire des cas à ça sera pareille. Dans le cas de la lecture simple, volatile est plus rapide.

    Citation Envoyé par thelvin Voir le message

    Ce n'est pas forcément dans ce sens-là que c'est préférable. Souvent, il vaut mieux prendre le temps de le faire au début que de ralentir une exécution normale plus tard. Après, tout dépend de quel genre d'application il s'agit, et de ce qui décide si oui ou non l'instance va être utilisée.
    Pour le pseudo "lazy loading", je suis d'accord que ça dépend avant tout de l'application. Sur une application serveur, le gain ne se justifie pas. Cependant dans une application Android, la réactivité et le chargement rapide de l'application est atout

  11. #11
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Vérifier sans arrêt la valeur d'une variable volatile n'est pas forcément mieux en termes de performances, les caches prennent cher, et une synchro peut souvent être assurée pour le même prix.
    +1 surtout en environnement multi-process/multi-core.

    Le volatile interdit au compilateur toute optimisation, puisqu'il doit à chaque fois vérifier la vrai valeur de la référence (même si celle-ci ne changera plus jamais après l'instanciation)



    Citation Envoyé par Yo Eight Voir le message
    Dans votre premier exemple, vous instanciez inutilement l'objet, ce qui peut ralentir le démarrage de votre application si sa construction nécessite des opérations lourdes.
    Les classes sont chargées lorsqu'on exécute un de leurs codes ou qu'on accède à un des leurs éléments.

    Pour un singleton ce sera donc lors de l'appel de getInstance() dans la plupart des cas... A moins qu'il ne possède d'autres attributs/méthodes static publique...



    Et si on veut vraiment déporter la création de l'instance, il suffit d'utiliser une classe interne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    final class Singleton {
     
    	private static class Holder {
    		private static final Singleton INSTANCE = new Singleton();
    	}
     
    	private Singleton() {
    		// ...
    	}
     
    	public static Singleton getInstance() {
    		return Holder.INSTANCE;
    	}
    }
    La classe "Holder" ne sera chargée que lors du premier appel de getInstance(). Tout comme notre instance de singleton

    De plus ce genre de code est très facile à optimiser pour un compilateur :
    • Il est très court et peut être facilement "inliné".
    • On fait un accès sur un champ static final. Il n'y a aucune synchro à faire puisqu'on est sûr que cette référence ne sera jamais modifié.


    a++

  12. #12
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    +1 surtout en environnement multi-process/multi-core.

    Le volatile interdit au compilateur toute optimisation, puisqu'il doit à chaque fois vérifier la vrai valeur de la référence (même si celle-ci ne changera plus jamais après l'instanciation)
    Je suis d'accord avec vous, cela dit, c'est surtout vrai dans le cas où on écrit et lit une variable volatile. Dans mon cas, ça reste que de la lecture simple.

    Citation Envoyé par adiGuba Voir le message
    Les classes sont chargées lorsqu'on exécute un de leurs codes ou qu'on accède à un des leurs éléments.

    Pour un singleton ce sera donc lors de l'appel de getInstance() dans la plupart des cas... A moins qu'il ne possède d'autres attributs/méthodes static publique...



    Et si on veut vraiment déporter la création de l'instance, il suffit d'utiliser une classe interne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    final class Singleton {
     
    	private static class Holder {
    		private static final Singleton INSTANCE = new Singleton();
    	}
     
    	private Singleton() {
    		// ...
    	}
     
    	public static Singleton getInstance() {
    		return Holder.INSTANCE;
    	}
    }
    La classe "Holder" ne sera chargée que lors du premier appel de getInstance(). Tout comme notre instance de singleton

    De plus ce genre de code est très facile à optimiser pour un compilateur :
    • Il est très court et peut être facilement "inliné".
    • On fait un accès sur un champ static final. Il n'y a aucune synchro à faire puisqu'on est sûr que cette référence ne sera jamais modifié.


    a++
    Je ne connaissais pas merci pour l'info

  13. #13
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Yo Eight Voir le message
    Je suis d'accord avec vous, cela dit, c'est surtout vrai dans le cas où on écrit et lit une variable volatile. Dans mon cas, ça reste que de la lecture simple.
    Tu lis la variable... mais est peut potentiellement être modifié dans un autre thread. Donc la JVM doit accéder à la variable et vérifier sa valeur à chaque fois. C'est le principe même du mot-clef volatile.


    Sans ce mot-clef, la JVM peut "optimiser" de multiple accès en considérant qu'elle n'est pas modifié dans d'autre thread, et qu'elle ne changera pas. Et c'est d'autant plus vrai lorsque le champs est final !



    Bien sûr la différence de performance est imperceptible dans la plupart des cas... mais elle existe surtout si on fait de la montée en puissance avec plusieurs milliers d'appels.


    Donc le "critère" performance laisse à désirer...



    a++

  14. #14
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Tu lis la variable... mais est peut potentiellement être modifié dans un autre thread. Donc la JVM doit accéder à la variable et vérifier sa valeur à chaque fois. C'est le principe même du mot-clef volatile.
    Pour moi, ce cas correspond plus à une erreur de conception car tu exposes un état (notre variable volatile) au monde externe. Pour moi ce que tu décris correspond à l'exposition de ta variable en tant que variable globale. Donc oui je suis d'accord, optimiser du code pas clean, c'est pas facile

    Encore une fois, dans mon cas (je ne parle pas d'utiliser une variable volatile dans tous les cas), il n'y aura pas ce genre de problème car on ne peut pas modifier ma variable dans un autre thread (cf. la "déférencer").

  15. #15
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Citation Envoyé par Yo Eight Voir le message
    Encore une fois, dans mon cas (je ne parle pas d'utiliser une variable volatile dans tous les cas), il n'y aura pas ce genre de problème car on ne peut pas modifier ma variable dans un autre thread (cf. la "déférencer").
    Ça, la JVM ne le sait pas. Par conséquent, elle fait tout comme si cette variable pouvait être modifiée dans un autre thread. C'est ce que fait volatile.
    Je ne vois pas pourquoi tu insistes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Yo Eight Voir le message
    Pour moi, ce cas correspond plus à une erreur de conception car tu exposes un état (notre variable volatile) au monde externe. Pour moi ce que tu décris correspond à l'exposition de ta variable en tant que variable globale. Donc oui je suis d'accord, optimiser du code pas clean, c'est pas facile
    Je ne parle pas forcément d'un code pas propre...

    Tu as ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private volatile static Singleton instance;
    La JVM ne peut pas savoir que tu ne vas modifier ce champ qu'une seule et unique fois. De plus le mot volatile lui indique que ce champ peut être modifié depuis différents threads.

    Elle devra impérativement vérifier l'état de la référence à chaque accès, car elle peut potentiellement changer !
    Même si c'est plus rapide que de la synchronisation, ca reste moins performant qu'un simple accès direct.

    En plus dans le code de ton getInstance() tu y accèdes au moins deux fois (une fois dans le if, et une fois pour le return).



    Citation Envoyé par Yo Eight Voir le message
    Encore une fois, dans mon cas (je ne parle pas d'utiliser une variable volatile dans tous les cas), il n'y aura pas ce genre de problème car on ne peut pas modifier ma variable dans un autre thread.
    Dans ton code oui. Mais via volatile tu indiques le contraire au compilateur et à la JVM...



    a++

  17. #17
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Merci pour vos éclaircissements, certains points m'étaient inconnus

  18. #18
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    d'après les specs volatile indique deux choses:
    - une obligation de consulter/modifier l'état de la variable dans la mémoire "principale" (pas dans une copie locale de la mémoire propre au thread)
    - mise en place d'un "avant" et d'un "après" cet accès. les optimisations de la JVM qui concernent le pipeline d'execution n'ont pas le droit de faire du réordonnancement de code qui "traverserait" cette instruction.

Discussions similaires

  1. demande de précision sur le mot-clef volatile
    Par archimondain dans le forum Threads & Processus
    Réponses: 13
    Dernier message: 01/03/2012, 20h27
  2. mot clef volatile précision
    Par guillaume07 dans le forum C++
    Réponses: 26
    Dernier message: 18/12/2010, 10h09
  3. mot clef volatile
    Par elmcherqui dans le forum C++
    Réponses: 4
    Dernier message: 11/04/2008, 22h25
  4. Mot clé volatile
    Par Invité dans le forum C
    Réponses: 6
    Dernier message: 27/10/2006, 12h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo