2012-02-17 24 views
25

Si en una clase tengo una instancia ConcurrentHashMap que será modificado y leído por múltiples hilos que podría definir así:¿Por qué una variable de miembro Object no puede ser definitiva y volátil en Java?

public class My Class { 

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

añadiendo final a los resultados de campo myMap en un error que dice que sólo puedo utilizar final o volátil. ¿Por qué no puede ser ambos?

+0

algo relacionado http://stackoverflow.com/questions/2964206/java-concurrency-volatile-vs-final- in -cascaded-variables – Jayan

Respuesta

23

volatile solo tiene relevancia para las modificaciones de la variable en sí, no el objeto al que se refiere. No tiene sentido tener un campo final volatile porque los campos finales no se pueden modificar. Simplemente declare el campo final y debería estar bien.

+0

simplemente para aclarar su comentario de que "los campos finales no se pueden modificar"; los campos finales son, de hecho, mutables, pero la palabra clave final solo permite que la asignación se realice una vez. – johntrepreneur

+3

@johnterpreneur: eso no es correcto; los campos finales se pueden asignar a * solo durante la construcción del objeto *, que es más o menos la definición de "inmutable". –

+0

si el uso de la palabra clave 'final' hizo que los objetos fueran inmutables como usted indicó, entonces declarar una variable de miembro' StringBuilder' final no le permitiría modificarla. Sin embargo, puede modificarlo y llamar a '.append' para cambiar el objeto. – johntrepreneur

2

volatile se utiliza para las variables que su valor puede cambiar, en ciertos casos, de lo contrario no hay necesidad de volatile, y final significa que la variable no puede cambiar, así que no hay necesidad de volatile.

Sus preocupaciones de concurrencia son importantes, pero haciendo que el HashMapvolátil no va a resolver el problema, para el manejo de los problemas de concurrencia, ya utiliza ConcurrentHashMap.

+0

No se puede hacer un HashMap (u otro objeto) 'volátil'. La palabra clave 'volátil' afecta la variable, no los objetos a los que la variable puede referirse. –

7

Debido volatile y final son dos extremos en Java

volatile significa que la variable está ligada a los cambios

final: el valor de la variable nunca va a cambiar en absoluto

1

Debido a que no lo hace ningún sentido. La volatilidad afecta el valor de referencia del objeto, no los campos del objeto/etc.

En su situación (tiene un mapa concurrente) debe hacer el campo final.

1

volatile modificador garantiza que todas las lecturas y escrituras Vaya estrecho a la memoria principal, es decir, al igual que la variable de acceso es casi en synchronized bloque. Esto es irrelevante para la variable final que no se puede cambiar.

21

Es a causa del Modelo de Memoria Java (JMM).

Básicamente, cuando declara el campo de objeto como final, necesita inicializarlo en el constructor del objeto y luego el campo final no cambiará su valor. Y JMM promete que después de que ctor finalice, cualquier subproceso verá el mismo valor (correcto) del campo final. Por lo tanto, no necesitará utilizar la sincronización explícita, como synchronize o Lock para permitir que todos los hilos vean el valor correcto del campo final.

Cuando declara el campo del objeto como volatile, el valor del campo puede cambiar, pero aún así cada lectura del valor de cualquier subproceso verá el último valor escrito en él.

Así, final y volatile logran el mismo propósito: la visibilidad del valor del campo del objeto, pero primero se usa específicamente para que una variable solo se pueda asignar una vez y la segunda se use para una variable que se puede cambiar muchas veces.

Referencias:

+0

La explicación es bastante buena para mí, sin embargo, no diría que la final se usa para valores 'constantes'. Esta afirmación es un poco engañosa, aunque entiendo lo que quería decir. –

+1

'"final y volátil" lograr el mismo propósito ... "Creo que eso es colocar el carrito delante del caballo. El _propósito_ de 'final' es declarar que una variable o campo no debe ser asignado. El _purpose_ de 'volátil' es decirle al compilador que el valor no se puede deducir examinando el código. El hecho de que el modelo de memoria Java tenga reglas especiales sobre la visibilidad de cada uno de esos dos tipos de variables es secundario a sus propósitos no superpuestos. –

4

Un campo volatile le da garantías como lo que sucede cuando se cambie. (No hay un objeto que podría ser una referencia a)

Un campo final no se puede cambiar (Lo que hacen referencia a los campos puede ser cambiado)

No tiene sentido tener ambos.

Cuestiones relacionadas