Si tengo un hilo invoca constantemente GETV y acabo de hacer una vez en SETV otro hilo, es que la lectura de hilo garantizado para ver el nuevo valor justo después de la escritura?
NO, el hilo de la lectura puede simplemente leer su propia copia (en caché de forma automática por el núcleo de la CPU, que el hilo se está ejecutando en la lectura) del valor v
's, y por lo tanto no obtener el valor más reciente.
¿O tengo que hacer que "V" sea volátil o AtomicReference?
SÍ, ambos funcionan.
Haciendo v
volátil simplemente detener núcleo de la CPU del valor de almacenamiento en caché v
's, es decir, cada operación de lectura/escritura a la variable v
deben tener acceso a la memoria principal, que es más lento (alrededor de 100x veces más lento que leer de caché L1, ver interaction_latency de detalles)
El uso de v = new AtomicInteger()
funciona porque AtomicInteger
usa un private volatile int value;
internamente para proporcionar visibilidad.
Y, también funciona si se utiliza bloqueo (si un objeto Lock
o utilizar synchronized
bloque o método) en la lectura y el hilo de escritura (como su segundo segmento de código hace), porque (según la sección Second Edition of The Java ® Virtual Machine Specification 8.9)
... bloqueo de cualquier cerradura vuelca conceptualmente todas las variables de la memoria de trabajo de un hilo , y desbloquear cualquier bloqueo fuerza la escritura a la memoria principal de todas las variables que el mensaje ha asignado ...
.. .Si un subproceso usa una variable compartida particular o después de bloquear un bloqueo particular y antes del desbloqueo correspondiente del mismo bloqueo , el hilo leerá el valor compartido de esa variable desde la memoria principal después de la operación de bloqueo, si es necesario, y copiará a la memoria principal. valor asignado más recientemente a esa variable antes de la operación de desbloqueo.Esto, en conjunto con las reglas de exclusión mutuos para las cerraduras, es suficiente para garantizar que los valores son transmitido correctamente desde un hilo a otro a través de las variables compartidas ...
P. S. AtomicXXX
también proporcionan operaciones CAS
(Compare and Swap) que es útil para el acceso mutththread.
P.P.S. La especificación jvm sobre este tema no ha cambiado desde Java 6, por lo que no están incluidas en jvm specification for java 7, 8, and 9.
P.P.P.S. De acuerdo con this article, las memorias caché de la CPU son siempre coherentes, independientemente de la vista de cada núcleo. La situación en su pregunta es causada por los 'Búferes de orden de la memoria', en los que las instrucciones store
& load
(que se utilizan para escribir y leer datos de la memoria, en consecuencia) podrían reordenarse por rendimiento. En detalle, el búfer permite una instrucción load
para adelantarse a una instrucción anterior store
, que causa exactamente el problema. Sin embargo, en mi opinión, esto es más difícil de entender, por lo que 'caché para diferentes núcleos (como lo hicieron las especificaciones de JVM)' podría ser un mejor modelo conceptual.
¿Quieres decir 'ReentrantLock'? –
Sí. Pero no solo ReentrantLock sino también ISchedulingRule e ILock del framework eclipse RCP. –