¿Cuál es la diferencia entre los métodos lazySet
y set
de AtomicInteger
? La documentación no tiene mucho que decir sobre lazySet
:
Eventualmente se establece en el valor dado.
Parece que el valor almacenado no se establecerá inmediatamente en el valor deseado, sino que se programará para establecerse en el futuro. Pero, ¿cuál es el uso práctico de este método? ¿Algún ejemplo?
fuente
Atomic*
alcance).lazySet se puede usar para la comunicación entre subprocesos rmw, porque xchg es atómico, en cuanto a la visibilidad, cuando el proceso del subproceso del escritor modifica la ubicación de una línea de caché, el procesador del subproceso del lector lo verá en la siguiente lectura, porque el protocolo de coherencia de caché de la CPU intel garantizará LazySet funciona, pero la línea de caché se actualizará en la siguiente lectura, nuevamente, la CPU tiene que ser lo suficientemente moderna.
http://sc.tamu.edu/systems/eos/nehalem.pdf Para Nehalem, que es una plataforma multiprocesador, los procesadores tienen la capacidad de "espiar" (espiar) el bus de direcciones para los accesos de otros procesadores a la memoria del sistema y a sus cachés internos. Usan esta capacidad de espionaje para mantener sus cachés internos consistentes tanto con la memoria del sistema como con los cachés en otros procesadores interconectados. Si al espiar un procesador detecta que otro procesador tiene la intención de escribir en una ubicación de memoria que actualmente tiene almacenada en caché en estado Compartido, el procesador de espionaje invalidará su bloque de caché y lo obligará a realizar un llenado de línea de caché la próxima vez que acceda a la misma ubicación de memoria. .
oracle hotspot jdk para arquitectura de cpu x86->
lazySet == unsafe.putOrderedLong == xchg rw (instrucción asm que sirve como una barrera blanda que cuesta 20 ciclos en la cpu intel nehelem)
en x86 (x86_64), dicha barrera es mucho más barata en términos de rendimiento que volátil o AtomicLong getAndAdd,
En un escenario de cola de un productor, un consumidor, la barrera suave xchg puede forzar la línea de códigos antes del lazySet (secuencia + 1) para que el hilo del productor ocurra ANTES de cualquier código del hilo del consumidor que consumirá (trabajará) los nuevos datos, por supuesto El hilo del consumidor deberá verificar atómicamente que la secuencia del productor se incrementó exactamente en uno usando un compareAndSet (secuencia, secuencia + 1).
Seguí el código fuente de Hotspot para encontrar la asignación exacta del lazySet al código cpp: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe. cpp Unsafe_setOrderedLong -> Definición de SET_FIELD_VOLATILE -> OrderAccess: release_store_fence. Para x86_64, OrderAccess: release_store_fence se define como el uso de la instrucción xchg.
Puede ver cómo se define exactamente en jdk7 (doug lea está trabajando en algunas cosas nuevas para JDK 8): http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/ linux_x86 / vm / orderAccess_linux_x86.inline.hpp
también puede usar hdis para desmontar el ensamblado del código lazySet en acción.
Hay otra pregunta relacionada: ¿Necesitamos mfence cuando usamos xchg?
fuente
Puede encontrar una discusión más amplia sobre los orígenes y la utilidad de lazySet y el putOrdered subyacente aquí: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html
Para resumir: lazySet es una escritura volátil débil en el sentido de que actúa como una tienda-tienda y no como una barrera de carga. Esto se reduce a que lazySet se compila con JIT en una instrucción MOV que el compilador no puede reordenar en lugar de la instrucción significativamente más cara que se usa para un conjunto volátil.
Al leer el valor siempre terminas haciendo una lectura volátil (con un Atomic * .get () en cualquier caso).
lazySet ofrece a un solo escritor un mecanismo de escritura volátil consistente, es decir, es perfectamente legítimo que un solo escritor use lazySet para incrementar un contador, varios subprocesos que incrementen el mismo contador tendrán que resolver las escrituras en competencia usando CAS, que es exactamente lo que sucede bajo las carátulas de Atomic * para incAndGet.
fuente
StoreStore
barrera simple , pero no unaStoreLoad
?Del resumen del paquete concurrente-atómico
lazySet tiene los efectos de memoria de escribir (asignar) una variable volátil excepto que permite reordenar con acciones de memoria posteriores (pero no previas) que no imponen restricciones de reordenamiento con escrituras no volátiles ordinarias. Entre otros contextos de uso, lazySet puede aplicarse al anular, en aras de la recolección de basura, una referencia a la que nunca se vuelve a acceder.
Si sientes curiosidad por lazySet, entonces también te debes otras explicaciones
fuente
Aquí está mi entendimiento, corríjame si me equivoco: puede pensar en
lazySet()
como "semi" volátil: es básicamente una variable no volátil en términos de lectura por otros hilos, es decir, el valor establecido por lazySet puede no ser visible para otros hilos. Pero se vuelve volátil cuando ocurre otra operación de escritura (puede ser de otros hilos). El único impacto de lazySet que puedo imaginar escompareAndSet
. Entonces, si lo usalazySet()
,get()
de otros subprocesos aún puede obtener el valor anterior, perocompareAndSet()
siempre tendrá el nuevo valor ya que es una operación de escritura.fuente
compareAndSet
?Re: intento de simplificarlo -
Puede pensar en esto como una forma de tratar un campo volátil como si no fuera volátil para una operación de tienda en particular (por ejemplo: ref = null;).
Eso no es del todo exacto, pero debería ser suficiente para que pudieras tomar una decisión entre "Está bien, realmente no me importa" y "Mmmm, déjame pensarlo un poco".
fuente