2012-11-28 10 views
7

Dalla documentazione:Errore di coerenza della memoria quando si utilizza la parola chiave volatile?

Utilizzo di variabili volatili riduce il rischio di errori di consistenza memoria

ma questo significa che le variabili a volte volatili non funzionano correttamente? Strano come possa essere usato - per mio parere è un codice pessimo che a volte funziona a volte no. Ho provato a Google ma non ho trovato alcun errore di consistenza della memoria di esempio con volatile. Potresti, per favore, proporne uno?

+1

Consiglio vivamente di leggere "Concurrency Java in pratica" di Brian Goetz. È su Amazon: http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1354080774&sr=8-1&keywords=java+concurrency+in+prodice –

+0

È un libro eccellente che demistificherà praticamente tutto ciò che riguarda la memoria e i modelli di threading di Java. –

risposta

10

Il problema non è tanto il fatto che volatile funzioni in modo inaffidabile. Funziona sempre come dovrebbe funzionare. Il problema è che il modo in cui dovrebbe funzionare a volte non è adeguato per il controllo della concorrenza. Se si utilizza volatile nella situazione errata, è ancora possibile ottenere errori di coerenza della memoria.

A variabile volatile verrà sempre propagata qualsiasi scrittura su tutti i thread. Tuttavia, supponiamo di dover incrementare la variabile tra i vari thread. In questo modo (*):

volatile int mCounter; 

// later, in some code that might be executed simultaneously on multiple threads: 
mCounter++; 

C'è una possibilità che incrementi del contatore ci mancherà. Questo perché il valore di mCounter deve essere prima letto da ogni thread prima che un nuovo valore possa essere scritto. Tra questi due passaggi, un altro thread potrebbe aver modificato il valore di mCounter. In situazioni come questa, è necessario fare affidamento sui blocchi synchronized anziché su volatile per garantire l'integrità dei dati.

Per maggiori informazioni su volatile vs synchronized, vi consiglio l'articolo Managing volatility di Brian Goetz

(*) mi rendo conto che quanto sopra sarebbe meglio implementato con AtomicInteger; è un esempio forzato per illustrare un punto.

4

volatile fa il seguente:

- E impedisce la memorizzazione nella cache i valori nel thread.

- Si assicura che i thread con le copie dei valori dei campi dell'oggetto si riconcilino con la copia principale presente nella memoria.

- Assicurarsi che i dati vengano scritti direttamente nella memoria e letti dalla memoria stessa.

## Ma la condizione in cui viene a mancare volatili:

- Fare un Non-Atomic statement Volatile.

Esempio:

int count = 0; 

count++; // Increment operator is Not Atomic in java 

## Opzione migliore:

1. sua sempre meglio seguire la Brian's Rule:

When ever we write a variable which is next to be read by another thread, or when we are reading a variable which is written just by another thread, it needs to be synchronized. The shared fields must be made private, making the read and write methods/atomic statements synchronized.

2. Seconda opzione è utilizzare il Atomic Classes, come AtomicInteger, AtomicLong, AtomicReference, ecc

## Vedi questo link, ho fatto una domanda simile come la tua:

Why Volatile is behaving weirdly

Problemi correlati