2013-08-08 12 views
7

Ho una variabile int foo a cui si accede da due thread. Supponendo di non avere problemi relativi alla condizione di razza (l'accesso è protetto da un mutex, tutte le operazioni sono atomiche, o qualsiasi altro metodo per proteggere dalle condizioni di gara), c'è ancora il problema di "registrare il caching" (per mancanza di un nome migliore) , in cui il compilatore può supporre che se la variabile viene letto due volte senza essere scritta in mezzo, è lo stesso valore, e così può "ottimizzare" le cose via come:`volatile` per la sincronizzazione variabile tra i thread

while(foo) { // <-may be optimized to if(foo) while(1) 
    do-something-that-doesn't-involve-foo; 
} 

o

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label; 
    do-something-that-doesn't-involve-foo; 
do-something-else-that-doesn't-involve-foo; 
if(foo) // <-may be optimized to jz label2; 
    do-something; 

la marcatura foo come volatile risolve questo problema? Le modifiche da un thread sono garantite per raggiungere l'altro thread?

In caso contrario, quale altro modo c'è per farlo? Ho bisogno di una soluzione per Linux/Windows (possibilmente soluzioni separate), senza C++ 11.

+0

ho ricordate di vedere una citazione dallo standard pronunciando la non suppone di utilizzare volatile per le discussioni più, in C++, cercherò di trovarlo – aaronman

+3

http: // StackOverflow.it/questions/4557979/when-to-use-volatile-with-multi-threading –

+1

Il problema qui è "Supponendo che non abbia problemi di condizioni di gara". Questa è un'ipotesi ** ENORME **. –

risposta

11

Quello che ti serve sono le barriere di memoria.

MemoryBarrier(); 

o

__sync_synchronize(); 

Edit: ho in grassetto la parte interessante e qui il link per l'articolo wiki (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) e il riferimento associato (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

ecco la risposta alla la tua altra domanda (da wikipedia): In C e C++, la parola chiave volatile aveva lo scopo di consentire ai programmi C e C++ di accedere direttamente all'I/O mappato in memoria. L'I/O mappato in memoria richiede in genere che le letture e le scritture specificate nel codice sorgente avvengano nell'ordine esatto specificato senza omissioni. Omissioni o riordini di letture e scritture da parte del compilatore interromperà la comunicazione tra il programma e il dispositivo a cui accede l'I/O mappato in memoria. Un compilatore C o C++ non può riordinare le letture e le scritture in posizioni di memoria volatile, né può omettere una lettura o scrittura in una posizione di memoria volatile. La parola chiave volatile non garantisce una barriera di memoria per imporre la coerenza della cache. Pertanto l'uso di "volatile" da sola non è sufficiente utilizzare una variabile per la comunicazione inter-thread su tutti i sistemi e processori [1]

controllare questo fuori, che fornisce ottimi spiegazioni sull'argomento: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

9

Se l'accesso è protetto da un mutex, non hanno alcun problema di cui preoccuparsi. La parola chiave volatile è inutile qui. Un mutex è una barriera di memoria completa e quindi nessun oggetto il cui indirizzo potrebbe essere visibile esternamente può essere memorizzato nella cache attraverso il blocco mutex o sbloccare le chiamate.

+0

Vero. Mutex si prende cura della coerenza della cache. – MasterPlanMan

+0

Per chiarezza: per cache intendevo non solo la cache a livello macchina, ma anche la cache dei valori del compilatore nei registri. –

1

La volatile parola chiave è stato originariamente introdotto per indicare che il valore può essere modificato dall'hardware. Questo accade quando il dispositivo hardware ha registri di memoria o buffer di memoria. L'approccio giusto è usarlo solo per questo scopo.

Tutti i moderni costrutti del linguaggio di sincronizzazione e le librerie di sincronizzazione non si utilizza questa parola chiave. I programmatori a livello di applicazione dovrebbero fare la stessa cosa.

Problemi correlati