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

C++ Discussion :

mot clef volatile


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif Avatar de elmcherqui
    Profil pro
    Inscrit en
    Février 2008
    Messages
    281
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Maroc

    Informations forums :
    Inscription : Février 2008
    Messages : 281
    Par défaut mot clef volatile
    bonjour ,
    lors de ma revision du langage C++ , j'ai decouvert un nouveau mot clef "volatile " . et je n'ai pas bien compris a quoi il peut servir malgres les explications du livre . son utilisation reste vague dans ma tete .
    donc si quelqu'un aurais l'amabilite de m'expliquer concretement a quoi il peut servir sa serais bien aimable .
    merci et bonne soiree .

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ça sert à indiquer que cette variable peut être modifiée à tout moment, notamment par un signal (ou en multithread sous certains systèmes, mais ce n'est pas garanti par le standard).
    Et donc, qu'il ne faut pas "optimiser" la lecture dans une boucle du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    volatile int a=0;
    CommencerUnTruc(&a);
     
    while(a==0)
    {
    	FaireUnTruc();
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Ça sert à indiquer que cette variable peut être modifiée à tout moment, notamment par un signal (ou en multithread sous certains systèmes, mais ce n'est pas garanti par le standard).
    Et donc, qu'il ne faut pas "optimiser" la lecture dans une boucle du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    volatile int a=0;
    CommencerUnTruc(&a);
     
    while(a==0)
    {
    	FaireUnTruc();
    }
    Et pour en rajouter une couche : un compilateur a le droit d'optimiser le chargement d'une variable à partir du moment ou cette optimisation ne change pas le fonctionnement du code. Il peut ainsi décider de stocker la variable dans un registre et de ne plus toucher ce registre par la suite. C'est quelque chose que les compilateurs font très souvent, par exemple dans ce cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int b = 1;
    while (b > 0)
    {
      we_just_call_a_function();
    }
    Une telle optimisation est forcément locale - elle ne peut pas prendre en compte le contexte global de l'application.

    Hors, un problème se pose dès lors que cette variable est utilisée autre part dans le code ou de manière désynchronisée. Par exemple :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    // in global.cpp
    int condition = 1000000;
     
    // in my_thread.h
    extern int condition;
    struct my_thread : public thread
    {
      virtual void body()
      {
        while (true)
        {
          --condition;
        }
      }
    }
     
    // in main.cpp
    #include "my_thread.h"
     
    extern int condition;
     
    int main()
    {
      my_thread t;
     
      t.run();
     
      while (condition > 0)
      {
        do_something();
      }
     
      t.terminate();
    }
    Dans ce pseudo-code (pseudo parce qu'il utilise une librairie de gestion de thread imaginaire), 2 thread se font concurrence sans se synchroniser (t, du type my_thread et la thread principale). On attends que la boucle while() dans main() ait fini de s'exécuter pour terminer t.

    Le problème est que si le compilateur décide d'optimiser l'accès à la variable condition (en chargeant la variable dans un registre pour ne plus y toucher après), la boucle dans main() ne se terminera jamais. Pour éviter ce problème et dire au compilateur que cette variable peut être modifiée de manière asynchrone ou sans qu'il ne le détecte dans une analyse locale du code, on déclare la variable comme étant volatile. Ce faisant, le compilateur sait que chaque fois qu'il aura une opération a effectuer sur cette variable, il lui sera nécessaire de relire la variable en mémoire avant d'effectuer cette opération.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Attention :
    au compilateur
    il faut que toutes les variables partagées soient volatiles. C'est à dire, tout ce qui est partagé directement ou indirectement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int valeur;
    volatile bool valide = false; // indique si valeur est remplie
     
    // dans thread 2 :
    valeur = ... résultat du calcul;
    valide = true;
     
     
    // dans thread 1 :
    while (! valide) { passer le temps }
    cout << valeur;
    Le compilateur ne peut pas optimiser les accès volatiles, mais il peut réordonner les accès non-volatiles par rapport aux accès volatiles, donc valide peut être positionné avant d'écrire valeur dans thread 2.

    Donc valeur doit être volatile aussi, ainsi que toutes les variables partagées sans synchronisation (et tous les objets partagés sans synchronisation).

    au processeur
    L'usage de volatile ne contrait que le comportement du compilateur, qui doit réellement faire les accès demandés.

    Un système multi-processeurs, que ce soit sous la forme bi-proc, dual-core ou même HyperThread (il me semble) ne garanti pas l'exécution dans l'ordre d'un programme multithread : il n'y a pas d'ordre global inter-threads. Le processeur peut réordonner les accès à valide et à valeur, d'une façon qui fasse apparaitre la valeur true de valide avant la valeur de valeur.

    Pour éviter cela il faudrait une barrière mémoire (memory fence) entre les affectations de valeur et valide, et entre les lectures de valide et de valeur.

    Les compilateurs n'insèrent généralement pas de barrière mémoire quand on utilise volatile (et on ne voit pas pourquoi ils le feraient, volatile de C++ n'est pas volatile de Java).

    En général, volatile n'est pas la solution à un problème de multitache (ce qui veut dire qu'il y a des exceptions).

  5. #5
    Membre très actif Avatar de elmcherqui
    Profil pro
    Inscrit en
    Février 2008
    Messages
    281
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Maroc

    Informations forums :
    Inscription : Février 2008
    Messages : 281
    Par défaut
    merci amis developpeurs pour cet exellente explication .

+ Répondre à la discussion
Cette discussion est résolue.

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, 19h27
  2. mot clef volatile précision
    Par guillaume07 dans le forum C++
    Réponses: 26
    Dernier message: 18/12/2010, 09h09
  3. mot clef sql pour nom de champ
    Par bobinou007 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 12/10/2004, 13h21

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