2008-11-11 19 views

Respuesta

89

respuesta corta es: No.

Desde el java.util.concurrent.atomic package doc:

Los efectos de memoria para accesos y actualizaciones de las atómicas generalmente siguen las reglas de volátiles:

  • get tiene la memoria efectos de leer una variable volatile.
  • set tiene los efectos de memoria de escribir (asignar) una variable volatile.

Por cierto, el doc para el paquete es muy bueno y todo se explica ...


lazySet (introducido en Java 6) es una operación más reciente introducido que tiene una semántica inalcanzables a través de volatile variables; ver this post para más información.

+2

Y la respuesta más larga sería? –

+0

De acuerdo. Al menos necesitamos un enlace. –

+2

El enlace para una respuesta más larga: http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/atomic/package-summary.html –

37

No, no lo hay.

La potencia adicional proporcionada por AtomicReference es el método compareAndSet() y sus amigos. Si no necesita esos métodos, una referencia volátil proporciona la misma semántica que AtomicReference.set() y .get().

3

AtomicReference proporciona funcionalidad adicional que una variable volátil no proporciona. Como ha leído la API, sabrá esto, pero también proporciona un bloqueo que puede ser útil para algunas operaciones.

Sin embargo, a menos que necesite esta funcionalidad adicional, le sugiero que utilice un campo simple volátil.

+0

Entonces, la diferencia está en Su desempeño. Si no hubiera diferencia, nunca recomendarías usar uno sobre el otro. –

+0

El rendimiento es muy similar. Un AtomicRefrence agrega complejidad y uso de memoria. –

+0

@BT Un campo 'volátil' se puede usar como cualquier campo regular, mientras que para acceder al valor en' AtomicReference' se debe pasar por los métodos 'get' y' set'. –

6

JDK source code es una de las mejores formas de responder a confusiones como esta. Si observa el código en AtomicReference, usa una variable volátil para el almacenamiento de objetos.

private volatile V value; 

Así que, obviamente, si se va a utilizar sólo get() y set() en AtomicReference es como usar una variable volátil. Pero como comentaron otros lectores, AtomicReference proporciona semántica de CAS adicional. Entonces, primero decida si quiere semántica de CAS o no, y si solo usa AtomicReference.

+8

* "El código fuente de JDK es una de las mejores formas de responder confusiones como esta" * => No necesariamente estoy de acuerdo, el javadoc (que es el contrato de la clase) es la mejor manera. Lo que encuentras en el código responde a la pregunta para una implementación específica, pero el código puede cambiar. – assylias

+3

Por ejemplo [esta variable] (http://stackoverflow.com/a/14363501/829571) en hashmap era volátil en JDK 6 pero ya no es volátil en Java 7. ¿Ha basado su código en el hecho de que la variable era volátil, se habría roto al actualizar tu JDK ... Es cierto que el ejemplo es diferente, pero entiendes el punto. – assylias

1

hay varias diferencias y compensaciones:

  1. Usando un AtomicReference get/set tiene el mismo semántica JMM como un campo volátiles (como los estados javadoc), pero el AtomicReference es una envoltura alrededor de una referencia, por lo que cualquier acceso al campo implica una persecución de puntero adicional.

  2. La huella memoria se multiplica (asumiendo un entorno OOPs comprimido, lo cual es cierto para la mayoría de las máquinas virtuales):

    • ref volátil = 4b
    • AtomicReference = 4b + 16b (cabecera de objeto 12b + Campo 4b ref)
  3. AtomicReference ofrece una API más rica que una referencia volátil. Puede recuperar la API para la referencia volátil utilizando AtomicFieldUpdater, o con Java 9 a VarHandle. También puede comunicarse directamente con sun.misc.Unsafe si le gusta correr con unas tijeras. AtomicReference en sí se implementa utilizando Unsafe.

lo tanto, cuando es bueno elegir una sobre la otra:

  • sólo necesitan obtener/poner? Quédese con un campo volátil, la solución más simple y la menor sobrecarga.
  • ¿Necesita la funcionalidad adicional? Si se trata de una parte sensible del rendimiento (velocidad/sobrecarga de memoria) de su código, haga una elección entre AtomicReference/AtomicFieldUpdater/Unsafe donde tiende a pagar en legibilidad y riesgo para su ganancia de rendimiento. Si esto no es un área sensible, solo haga clic en AtomicReference. Los escritores de bibliotecas suelen utilizar una combinación de estos métodos según los JDK específicos, las restricciones esperadas de la API, las limitaciones de memoria, etc.
Cuestiones relacionadas