2012-02-17 22 views
25

Se in una classe ho un esempio ConcurrentHashMap che sarà modificato e letto da più thread che potrei definire così:Perché una variabile membro dell'oggetto non può essere sia finale che volatile in Java?

public class My Class { 

    private volatile ConcurrentHashMap<String,String> myMap = new ConcurrentHashMap<String,String>(); 
... 
} 

aggiungendo final per i risultati del campo myMap un errore dicendo che posso usare solo finale o volatile. Perché non può essere entrambi?

+0

un po 'correlato http://stackoverflow.com/questions/2964206/java-concurrency-volatile-vs-final-in-cascaded-variables – Jayan

risposta

23

volatile ha rilevanza solo per le modifiche della variabile stessa, non l'oggetto a cui si riferisce. Non ha senso avere un campo final volatile perché i campi finali non possono essere modificati. Basta dichiarare il campo final e dovrebbe andare bene.

+0

proprio come per chiarire il tuo commento che "i campi finali non possono essere modificati"; i campi finali sono, infatti, mutabili, ma la parola chiave finale consente solo l'assegnazione di una sola volta. – johntrepreneur

+3

@johnterpreneur: non è corretto; i campi finali possono essere assegnati a * solo durante la costruzione dell'oggetto *, che è praticamente la definizione di "immutabile". –

+0

se l'uso della parola chiave 'final' ha reso gli oggetti immutabili come dichiarato, quindi dichiarare una variabile membro' StringBuilder' non consente di modificarlo. Comunque puoi modificarlo e chiamare '.append' per cambiare l'oggetto. – johntrepreneur

2

volatile viene utilizzato per le variabili che il loro valore può cambiare, in alcuni casi, in caso contrario non v'è alcuna necessità di volatile, e final significa che la variabile non può cambiare, quindi non c'è bisogno di volatile.

Le vostre preoccupazioni di concorrenza sono importanti, ma rendendo il HashMapvolatili non risolverà il problema, per la gestione dei problemi di concorrenza, si utilizza già ConcurrentHashMap.

+0

Non è possibile creare una HashMap (o qualsiasi altro oggetto) 'volatile'. La parola chiave 'volatile' influenza la variabile, non gli oggetti a cui la variabile può riferirsi. –

7

Poiché volatile e final sono due estremi in Java

volatile intende la variabile è associata a variazioni

final intende il valore della variabile cambierà mai alcuna

1

Poiché non fa ha senso Volatile influisce sul valore di riferimento dell'oggetto, non sui campi dell'oggetto/ecc.

Nella tua situazione (hai una mappa concomitante) dovresti fare il campo final.

1

volatile modificatore garantisce che tutte le letture e le scritture vadano alla memoria principale, ad esempio l'accesso variabile è quasi nel blocco synchronized. Questo è irrilevante per la variabile finale che non può essere modificata.

21

È a causa di Java Memory Model (JMM).

In sostanza, quando si dichiara campo oggetto come final è necessario inizializzarlo nella funzione di costruzione dell'oggetto e quindi il campo final non modificherà il valore. E JMM promette che dopo che ctor è finito, qualsiasi thread vedrà lo stesso valore (corretto) del campo final. Pertanto, non è necessario utilizzare la sincronizzazione esplicita, ad esempio synchronize o Lock per consentire a tutti i thread di visualizzare il valore corretto del campo final.

Quando si dichiara il campo dell'oggetto come volatile, il valore del campo può cambiare, ma comunque ogni lettura di valore da qualsiasi thread vedrà l'ultimo valore scritto su di esso.

Quindi, final e volatile conseguire stesso scopo - visibilità del valore del campo dell'oggetto, ma prima è specifico per una variabile può essere assegnata una volta sola seconda è utilizzato per una variabile che può essere modificata molte volte.

Riferimenti:

+0

La spiegazione è abbastanza buona per me, tuttavia non direi che il finale è usato per valori 'costanti'. Questa affermazione è un po 'fuorviante, anche se capisco cosa volevi dire. –

+1

'"finale e volatile" raggiunge lo stesso scopo ...' Penso che stia mettendo il carro davanti ai buoi. Il _purpose_ di 'final' è quello di dichiarare che una variabile o campo non deve essere assegnato. Lo scopo di 'volatile' è di dire al compilatore che il valore non può essere dedotto esaminando il codice. Il fatto che il modello di memoria Java abbia regole speciali sulla visibilità di ciascuno di questi due tipi di variabile è secondario rispetto ai loro scopi non sovrapposti. –

4

Un campo volatile ti dà garanzie di ciò che accade quando si cambia. (Non un oggetto che potrebbe essere un riferimento a)

Un campo final non può essere modificato (Cosa fanno riferimento i campi può essere modificato)

Non ha senso avere entrambi.

Problemi correlati