Le mot-clé volatile informe le compilateur qu'une variable peut changer de manière inattendue pour celui-ci (par exemple, par le matériel, un autre fil ou un gestionnaire d'interruption), et interdit de mettre en cache sa valeur ou d'optimiser ses accès.
Utilisé pour :
volatile ne garantit pas l'atomicité ou la synchronisation !).volatile int flag = 0; void handler() { flag = 1; // gestionnaire d'interruption } void loop() { while (!flag) { // attend un événement } // ... }
Sans volatile, le compilateur aurait pu remplacer la boucle par une boucle infinie (ne pas lire flag de la mémoire), avec volatile, la variable est lue à chaque fois de la mémoire.
Est-il suffisant d'utiliser volatile pour échanger correctement des informations entre des fils ?
Une erreur fréquente - penser que volatile assure la synchronisation de la mémoire entre les fils et rend les opérations atomiques.
Réponse correcte :
volatile ne protège pas contre les conditions de course dans un environnement multithread et n'assure pas de barrières de mémoire : il indique simplement au compilateur de ne pas optimiser l'accès. Pour une garantie de correction, il est essentiel d'utiliser des primitives de synchronisation (mutex, opérations atomic, etc.).
// Ce n'est pas sûr ! volatile int ready = 0; void thread1() { data = 123; // écriture de données ready = 1; // signal à un autre fil } void thread2() { while (!ready); // attente d'un événement printf("data = %d\n", data); // il se peut que data ne soit pas encore mis à jour ! }
Histoire