Contrassegnare una variabile come volatile
in Java assicura che ogni thread visualizzi il valore che è stato scritto su di esso anziché un valore scaduto. Mi stavo chiedendo come questo sia stato effettivamente raggiunto. La JVM emette istruzioni speciali per lo svuotamento della CPU o qualcosa del genere?Come funziona davvero volatile?
risposta
Da quello che ho capito sembra sempre che la cache sia stata svuotata dopo la scrittura, e appare sempre come se le letture venissero eseguite direttamente dalla memoria in lettura. L'effetto è che un thread vedrà sempre i risultati delle scritture da un altro thread e (secondo il modello di memoria Java) mai un valore memorizzato nella cache. L'effettiva implementazione e le istruzioni della CPU varieranno comunque da un'architettura all'altra.
Non garantisce la correttezza se si incrementa la variabile in più di un thread, oppure si controlla il suo valore e si agisce perché ovviamente non esiste alcuna sincronizzazione effettiva. In genere, è possibile garantire l'esecuzione corretta solo se nella variabile è presente solo la scrittura di Thread e gli altri stanno tutti leggendo.
Si noti inoltre che una variabile NON volatile a 64 bit può essere letta/scritta come due variabili a 32 bit, quindi le variabili a 32 bit sono atomiche in scrittura ma quelle a 64 bit no. Una metà può essere scritta prima di un'altra - quindi il valore letto potrebbe essere inferiore al vecchio o al nuovo valore.
Questo è piuttosto utile pagina dai miei preferiti:
@jgubby: il tuo ultimo paragrafo non sembra corretto: non puoi leggere un volatile a 64 bit che avrebbe 32 bit da una scrittura e l'altro da 32 bit da un'altra scrittura. – SyntaxT3rr0r
@WizardOfOdds: concordato. Significa dire variabile NON-volatile lì. – gubby
@jbuggy: ah ah, questo è quello che pensavo ma non ho osato modificare il tuo post perché non ero sicuro di cosa volevi dire :) Sono contento di aiutarti, perché altrimenti è stato un po 'confuso :))) – SyntaxT3rr0r
Esattamente ciò che accade è specifico del processore. Generalmente ci sono alcune istruzioni sulla barriera della memoria. Flushing dell'intera cache sarebbe ovviamente molto costoso - ci sono protocolli di coerenza della cache nell'hardware.
È inoltre importante che alcune ottimizzazioni non vengano eseguite attraverso gli accessi al campo. Il compilatore è importante quando si considera il multithreading, non pensare solo all'hardware.
Esattamente ciò che accade in un programma Java scritto correttamente non è specifico del processore. – gubby
@jgubby La domanda chiede se vengono emesse istruzioni speciali. –
questione connessa (il primo della lista in realtà ..) http://stackoverflow.com/questions/1787450/how-do- i-understand-read-memory-barriers-and-volatile – BalusC
E un thread che ho iniziato su volatile con molti "upvotes" e "preferiti" relativi all'esecuzione fuori ordine: http://stackoverflow.com/questions/2441279/java-volatile-guarantee-and-out-of-order-execution – SyntaxT3rr0r