practice - thread java
Referencia volátil Java vs. AtomicReference (5)
AtomicReference proporciona una 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 use un campo simple volátil.
¿Hay alguna diferencia entre una referencia de Objeto volatile
y AtomicReference
en caso de que use simplemente get()
y set()
AtomicReference
de AtomicReference
?
Hay varias diferencias y compensaciones:
El uso de un get / set
AtomicReference
tiene la misma semántica de JMM que un campo volátil (como dice javadoc), peroAtomicReference
es un contenedor alrededor de una referencia, por lo que cualquier acceso al campo implica una persecución de puntero adicional .La huella de memoria se multiplica (suponiendo un entorno de OOP comprimido, que es cierto para la mayoría de las máquinas virtuales):
- ref volátil = 4b
-
AtomicReference
= 4b + 16b (cabecera del objeto 12b + campo de referencia 4b)
AtomicReference
ofrece una API más rica que una referencia volátil. Puede recuperar la API para la referencia volátil utilizando unAtomicFieldUpdater
, o con Java 9 aVarHandle
. También puedesun.misc.Unsafe
directamente asun.misc.Unsafe
si le gusta correr con tijeras.AtomicReference
sí mismo se implementa utilizandoUnsafe
.
Entonces, ¿cuándo es bueno elegir uno sobre el otro?
- ¿Solo necesita get / set? 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 no es una zona sensible, solo tiene que ir aAtomicReference
. 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.
La respuesta corta es: No.
Del documento del paquete java.util.concurrent.atomic :
Los efectos de memoria para los accesos y las actualizaciones de atomics generalmente siguen las reglas para volátiles:
get
tiene los efectos de memoria de leer una variablevolatile
.set
tiene los efectos de memoria de escribir (asignar) una variablevolatile
.
Por cierto, el documento del paquete es muy bueno y todo se explica ...
lazySet
(introducido en Java 6) es una nueva operación introducida que tiene una semántica inalcanzable a través de variables volatile
; vea esta publicación para más información.
No no hay.
La potencia adicional proporcionada por AtomicReference es el método y amigos CompareAndSet (). Si no necesita esos métodos, una referencia volátil proporciona la misma semántica que AtomicReference.set () y .get ().
El código fuente de JDK 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 vas a usar 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.