Purtroppo la semantica volatile è piuttosto sdolcinata. Il concetto di volatile non era realmente pensato per essere utilizzato per il threading.
Potatoswatter è corretto che chiamare le primitive di sincronizzazione del sistema operativo normalmente impedirà al compilatore di ottimizzare di sollevare la lettura di num dal ciclo. Ma funziona per sorta la stessa ragione per cui l'utilizzo di un metodo accessor funziona ... per caso.
Il compilatore vede che si chiama una funzione che non è immediatamente disponibile per l'inlining o l'analisi, quindi deve presumere che qualsiasi variabile che potrebbe essere utilizzata da qualche altra funzione potrebbe essere letta o alterata in quella opaca funzione. Quindi, prima di effettuare la chiamata, il compilatore deve scrivere tutte quelle variabili "globali" in memoria.
In corensic, abbiamo aggiunto una funzione inline a jinx.h che lo fa in modo più diretto. Qualcosa di simile a quanto segue:
inline void memory_barrier() { asm volatile("nop" ::: "memory"); }
Questo è piuttosto sottile, ma dice effettivamente il compilatore (GCC) che non può sbarazzarsi di questo pezzo di asm opaco e che l'asm opaca in grado di leggere o scrivere qualsiasi livello globale pezzo di memoria visibile. Questo impedisce al compilatore di riordinare carichi/negozi attraverso questo limite.
Per esempio:
memory_barrier(); while (num == 0) { memory_barrier(); ... }
Ora la lettura di num è bloccata. E potenzialmente più importante, è bloccato sul posto rispetto ad altri codici. Così si potrebbe avere:
while (flag == 0) { memory_barrier(); } // spin
process data[0..N]
E un altro thread fa:
populate data[0..N]
memory_barrier();
flag = 1;
PS.Se fai questo tipo di cose (essenzialmente creando le tue primitive di sincronizzazione) le vittorie perf possono essere grandi ma il rischio di qualità è alto. Jinx è particolarmente adatto a trovare bug in queste strutture prive di lock. Quindi potresti voler usarlo o qualche altro strumento per testare questa roba.
PPS. La comunità linux ha un bel post su questo chiamato "volatile considerato dannoso", dai un'occhiata.
Controllare questa domanda (http://stackoverflow.com/questions/3148319/is-volatile-richiesta-per-combinato-memoria-accesso-via-accesso-funzione). – gablin