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

Threads & Processus C++ Discussion :

demande de précision sur le mot-clef volatile


Sujet :

Threads & Processus C++

  1. #1
    Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut demande de précision sur le mot-clef volatile
    Bonjour
    J'ai un programme avec 2 threads sur une architecture classique 32 bits , et j'ai des variables de type simple (int) à protéger à la fois d'un accès concurrent écriture/écriture, et d'un accès concurrent lecture/écriture.

    Le mot clef volatile me protège contre un accès écriture/écriture.
    Mais je ne sais pas si il protège aussi un accès concurrent lecture/écriture.
    Quelqu'un aurait-il la réponse ? (un thread peut-il lire la valeur d'une variable au même moment ou un autre est en train de la modifier, et lire alors une valeur érronée, ou lira-t-il forcément soit la valeur juste avant la modification, soit la valeur juste après ?)

    Merci d'avance

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Le mot clé volatile indique uniquement au compilateur à ne pas faire de simplification sur la lecture. Il indique que cette variable peut être modifiée de manière externe.

    Exemple avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int val = 1;
    while(val == 1)
    {
    }
    Le compilateur pourrait très bien simplifier en ignorant la variable val et en écrivant quelque chose comme cela (puisque val n'est pas utilisé) :
    Le fait de mettre le mot clé "volatile" indique au compilateur qu'il ne doit pas faire de simplifications.

    Le mot clé volatile trouve son utilité dans le cas d'une variable du programme dont la valeur peut être modifiée par une interruption (donc hors contexte du programme).
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut
    Merci,
    Mais ça ne répond pas à ma question

    En fait je devrais sans doute reformuler :

    Sur une architecture classique, 32 bits, avec 2 processeurs (précision qui a son importance)
    - un premier thread va effectuer une opération d'assembleur pour lire un emplacement mémoire de 4 octets.
    - un deuxième thread va effectuer une opération d'assembleur pour écrire dans ce même emplacement mémoire.

    la valeur lue par le premier thread pourra-t-elle être incohérente, ou sera-t-elle forcément soit une valeur présente avant l'écriture du deuxième thread, soit une valeur présente après l'écriture du deuxième thread ?

    Merci d'avance

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par archimondain Voir le message
    Mais ça ne répond pas à ma question
    Alors le titre du post n'est pas adéquat

    Dans ton cas, il faudra passer par des opérations de lectures/écritures atomiques.

    Je ne connais pas ton OS cible mais sous Windows, regarde du côté des Interlocked variable access

    Lu ici : Interlocked Variable Access
    Simple reads and writes to properly-aligned 32-bit variables are atomic operations. In other words, you will not end up with only one portion of the variable updated; all bits are updated in an atomic fashion. However, access is not guaranteed to be synchronized. If two threads are reading and writing from the same variable, you cannot determine if one thread will perform its read operation before the other performs its write operation.

    Simple reads and writes to properly aligned 64-bit variables are atomic on 64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be atomic on 32-bit Windows. Reads and writes to variables of other sizes are not guaranteed to be atomic on any platform.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Comme le dit ram-0000, volatile ne garantie rien en terme de multithread. Si tu as un risque de race condition, il faut protéger. volatile dit juste que la variable peut changer hors du contexte de son utilisation immédiate (les fameuses interruptions) et donc éviter certaines optimisations qui auraient pu avoir lieu par ailleurs.

  6. #6
    Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut
    Merci pour vos réponses
    Effectivement j'aurai du poster ailleurs.
    Ce que je comprend c'est que volatile me garantis que mes opérations lecture/ecriture s'effectuerons bien dans le même emplacement mémoire (et pas dans un registre ou autre optimisation du compilo).

    J'ai fait quelques tests, et sur une architecture 32 bits avec plusieurs processeurs, les opérations de lecture/écriture sur 4 octets sont bien atomiques, et il ne semble pas y avoir de risque qu'un thread lise les 4 octets alors que l'autre a modifié les deux premiers sans modifier les deux derniers.

    Quand il n'y a que des accès a des variables de type simple sur 4 octets à protéger (entier, float, pointeur), il semble donc superflue d'utiliser des mutex, le mot-clef volatile suffit.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par archimondain Voir le message
    Merci pour vos réponses
    Effectivement j'aurai du poster ailleurs.
    Ce que je comprend c'est que volatile me garantis que mes opérations lecture/ecriture s'effectuerons bien dans le même emplacement mémoire (et pas dans un registre ou autre optimisation du compilo).
    En fait, la valeur est lue en mémoire au moment de son utilisation (et non en cache) et que l'endroit où a lieu cette lecture n'est pas modifié par une optimisation.

    Citation Envoyé par archimondain Voir le message
    J'ai fait quelques tests, et sur une architecture 32 bits avec plusieurs processeurs, les opérations de lecture/écriture sur 4 octets sont bien atomiques, et il ne semble pas y avoir de risque qu'un thread lise les 4 octets alors que l'autre a modifié les deux premiers sans modifier les deux derniers.

    Quand il n'y a que des accès a des variables de type simple sur 4 octets à protéger (entier, float, pointeur), il semble donc superflue d'utiliser des mutex, le mot-clef volatile suffit.
    1 question :
    -> moi, je comprend que l'instruction d'écriture (ou de lecture) en mémoire est atomique : soit les 4 octets sont écris (lus) soit il ne le sont pas. En revanche, l'opération de lecture/écriture en C++, elle n'est pas atomique. Ainsi (j'ai mis le code ASM de visual 9 en debug) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int retour;
    int var;
     
    retour = 0; //   --> atomique
    //   mov         dword ptr [retour],0   --> atomique
     
    retour = var_;   --> NON atomique
    //   mov         eax,dword ptr [var_]    --> lecture de 'var_' atomique
    //   mov         dword ptr [retour],eax    --> ecriture de 'retour' atomique
     
    retour = retour + 1; //   --> NON atomique
    //   mov         eax,dword ptr [retour]    --> lecture de 'retour' atomique
    //   add         eax,1  --> addition
    //   mov         dword ptr [retour],eax    --> ecriture du résultat dans 'retour' atomique
    Ce qui me laisse penser que tu n'es pas à l'abri de problèmes en cas d'écritures simultanées.
    1 remarque :
    -> dès que tu changeras d'architecture/d'OS, ces hypothèses seront caduques et tu t'exposes à ce que le code ait un comportement erratique.

  8. #8
    Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Par défaut
    merci pour cette précision.

    c'est effectivement quelque chose à prendre en considération.
    Dans mon cas tou se passe bien, car lors d'une affectation de type

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    volatile int shared_var;
    int value;
    shared_var = value;
    seule la variable qui reçoit l'affectation est partagée par plusieurs thread, l'autre étant propre à chaque thread.

    C'est vrai que mon code ne fonctione pas sur toutes les architectures, en revanche, il me paraitrait logique que l'atomicité des opérations ne dépendent pas de l'OS. En tout cas j'ai testé sous linux et windows, et ça se passe bien dans les deux cas.

    De manière général, je suis d'accord avec toi, et je crois qu'il vaut mieux éviter de s'appuyer sur un détail aussi bas niveau pour faire son programme.

    Mais dans mon cas j'ai de grosses contraintes de rapidité, et le fait de ne pas utiliser de mutex augmente ma vitesse d'éxecution de facon directement proportionnel au nombre de processeurs dont je dispose, ce qui n'est pas du tout le cas quand j'utilise des mutex.

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par archimondain Voir le message
    Mais dans mon cas j'ai de grosses contraintes de rapidité, et le fait de ne pas utiliser de mutex augmente ma vitesse d'éxecution de facon directement proportionnel au nombre de processeurs dont je dispose, ce qui n'est pas du tout le cas quand j'utilise des mutex.
    Effectivement, la synchronisation a un coût. Mais, une des solutions est aussi de voir comment couper cette inter-dépendance des 2 threads sur la même donnée.

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Par défaut
    Je remonte un vieux sujet...

    Je voulais préciser que pour qu'une opération de lecture ou d'écriture 32 bits soit atomique (sur un système 32 bits),
    il faut que l'adresse de la lecture/écriture soit alignée (multiple de 4 octets).
    Dans le cas contraire, je pense que 2 opérations seront réalisées.
    Connaissez-vous une directive C pour indiquer à une variable d'être alignée en mémoire ? (je crois savoir que cela est automatique pour les mémoires partagées).

    Autre question, l'utilisation du mot clef 'volatile' indique t'il uniquement au compilateur de ne pas optimiser les accès en lecture / écriture à la variable ou indique t'il également de ne pas utiliser le cache ?
    L'utilisation ou non du cache a t-elle une conséquence sur la communication inter-thread (ou inter-precessus) dans le cas d'un accès concurrent lecture/écriture ?

    Merci de vos réponses!

  11. #11
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    volatile n'apporte aucune garantie sur le plan MT.

    Si ta préoccupation est liée à des aspects MT, oublie volatile. Définitivement -- sauf si tu utilises une mouture récente de VC++ (et VC++ seul -- et récent) qui a détourné le mot clé.
    Le C++11 apporte son lot de nouveautés qui solutionne les problèmes que l'on voulait refiler à volatile.

    Sinon, lectures pour les sceptiques
    - http://www.alexonlinux.com/multithre...omic-variables
    - http://software.intel.com/en-us/blog...d-programming/

    Et un petit détournement:
    - http://drdobbs.com/cpp/184403766 (utilisation de volatile pour son côté cv-qualifier viral)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Par défaut
    Salut,

    merci pour tes réponses.
    Je ne connaissais pas les fonctions atomiques __sync_fetch_and_xxx.
    Je ne peux malheureusement pas les utiliser avec ma version de gcc (3.4).

    D'après ce que j'ai compris, le 'volatile' n'est pas utile si on utilise des mutex, ce que je fais actuellement.
    Le 'volatile' étant plus rapide que le mutex, je vais essayer de le mettre en place pour certaines variables (par exemple celle que je scrute pour savoir si il faut terminer le thread).

  13. #13
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Si une variable n'est accédée en écriture que par un thread, alors volatile est à envisager ; à condition que les autres threads sachent que la valeur de la variable peut être modifié même au cours d'une expression comme i + i.

    Ce qui peut gêner parfois. En effet, assert(i+i == i*2), parfaitement valide en mono-thread, est potentiellement invalide en multithread, même si i est volatile.

    Mais dès qu'une variable est accédée en écriture par plusieurs threads, volatile est strictement inutile, même en connaissant les restrictions sus-citées.

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    VOLATILE NE GARANTIT RIEN D'UN POINT DE VUE MT


    Cf les articles proposés par Luc entre autres. volatile est principalement utilisé pour accéder à des registres mappés en mémoire et là il est indispensable.

Discussions similaires

  1. mot clef volatile précision
    Par guillaume07 dans le forum C++
    Réponses: 26
    Dernier message: 18/12/2010, 09h09
  2. Demande de précision sur clef étrangère
    Par MistyMan dans le forum Débuter
    Réponses: 2
    Dernier message: 06/11/2008, 01h21
  3. [final]demande d'explication sur ce mot-clé
    Par Invité dans le forum Langage
    Réponses: 10
    Dernier message: 18/04/2006, 11h32
  4. Demande de précision sur "Extends" ..
    Par Invité dans le forum Langage
    Réponses: 6
    Dernier message: 12/02/2006, 14h25
  5. Demande de précisions sur Backup/Restore et transactions
    Par lio33 dans le forum Connexion aux bases de données
    Réponses: 1
    Dernier message: 16/11/2005, 12h08

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