Desafortunadamente la semántica volátil es un poco desagradable. El concepto de volátil no estaba realmente destinado a ser utilizado para enhebrar.
Potatoswatter es correcto que llamar a las primitivas de sincronización del sistema operativo normalmente evitará que el compilador de optimización eleve la lectura de num del bucle. Pero funciona por la misma razón por la que el uso de un método de acceso funciona ... por accidente.
El compilador lo ve llamando a una función que no está inmediatamente disponible para alineación o análisis, por lo que tiene que suponer que cualquier variable que podría ser utilizada por alguna otra función podría leerse o alterarse en esa función opaca. Entonces, antes de hacer la llamada, el compilador necesita volver a escribir en la memoria todas esas variables "globales".
En corensic, agregamos una función en línea a jinx.h que hace esto de una manera más directa. Algo así como lo siguiente:
inline void memory_barrier() { asm volatile("nop" ::: "memory"); }
Esto es bastante sutil, pero efectivamente le dice al compilador (gcc) que no puede deshacerse de este trozo de asm opaca y que el asm opaca puede leer o escribir cualquier nivel mundial pedazo de memoria visible. Esto efectivamente detiene el compilador de reordenar cargas/tiendas a través de este límite.
Para su ejemplo:
memory_barrier(); while (num == 0) { memory_barrier(); ... }
Ahora la lectura de num está pegada en su lugar. Y potencialmente más importante, está atascado en su lugar con relación a otro código. Por lo que podría tener:
while (flag == 0) { memory_barrier(); } // spin
process data[0..N]
Y otro hilo hace:
populate data[0..N]
memory_barrier();
flag = 1;
PS.Si haces este tipo de cosas (esencialmente creando tus propias primitivas de sincronización), las ganancias de rendimiento pueden ser grandes pero el riesgo de calidad es alto. Jinx es particularmente bueno para encontrar errores en estas estructuras sin cerrojo. Así que es posible que desee usarlo o alguna otra herramienta para ayudar a probar esto.
PPS. La comunidad de Linux tiene una buena publicación sobre esto llamada "volátil considerado perjudicial", compruébalo.
Marque esta pregunta (http://stackoverflow.com/questions/3148319/is-volatile-required-for-shared-memory-accessed-via-access-function). – gablin