La palabra clave volatile informa al compilador que una variable puede cambiar de manera inesperada para el compilador (por ejemplo, por hardware, otro hilo o un controlador de interrupciones) y prohíbe almacenar en caché su valor o optimizar los accesos a ella.
Se utiliza:
volatile no garantiza atomicidad o sincronización!).volatile int flag = 0; void handler() { flag = 1; // controlador de interrupciones } void loop() { while (!flag) { // esperando evento } // ... }
Sin volatile, el compilador podría reemplazar el ciclo por uno infinito (sin leer flag de la memoria); con volatile, la variable se lee cada vez de la memoria.
¿Es suficiente usar volatile para el intercambio correcto de información entre hilos?
Un error común es pensar que volatile asegura la sincronización de memoria entre hilos y hace que las operaciones sean atómicas.
Respuesta correcta:
volatile no protege contra condiciones de carrera en entornos multihilo y no proporciona barreras de memoria: solo le dice al compilador que no optimice el acceso. Para garantías de corrección, es imprescindible usar primitivas de sincronización (mutex, operaciones atomic, etc.).
// ¡Esto no es seguro! volatile int ready = 0; void thread1() { data = 123; // escritura de datos ready = 1; // señal a otro hilo } void thread2() { while (!ready); // esperando evento printf("data = %d ", data); // ¡posiblemente data aún no se ha actualizado! }
Historia