java - apereo - ¿Qué significa "falla espuria" en AtomicInteger weakCompareAndSet?
cas server (4)
Pero, ¿por qué se permite que eso suceda? ¿Esto es porque el hardware / sistema operativo subyacente tiene errores? ¿O hay alguna buena razón técnica detrás de esto?
La clase Java AtomicInteger tiene un método:
boolean weakCompareAndSet(int expect,int update)
Su documnentation dice:
Puede fallar falsamente.
¿Qué significa "fallar falsamente" aquí?
Significa que puede devolver falso (y no establecerá el nuevo valor) incluso si actualmente contiene el valor esperado.
En otras palabras, el método puede no hacer nada y devolver falso sin ninguna razón aparente ...
Hay arquitecturas de CPU donde esto puede tener una ventaja de rendimiento sobre un fuerte CompareAndSet()
.
Un poco más de detalle concreto sobre por qué algo así podría suceder.
Algunas arquitecturas (como las ARM más nuevas) implementan operaciones CAS utilizando un conjunto de instrucciones Load Linked (LL) / Store Conditional (SC). La instrucción LL carga el valor en una ubicación de memoria y ''recuerda'' la dirección en alguna parte. La instrucción SC almacena un valor en esa ubicación de memoria si el valor en la dirección recordada no se ha modificado. Es posible que el hardware crea que la ubicación ha sido modificada incluso si aparentemente no lo ha sido por varias razones posibles (y las razones pueden variar según la arquitectura de la CPU):
- la ubicación puede haber sido escrita con el mismo valor
- la resolución de las direcciones observadas podría no ser exactamente la ubicación de memoria de interés (líneas de memoria). Una escritura en otra ubicación que está "cerca" puede hacer que el hardware marque la dirección en cuestión como "sucia"
- un número de otras razones que pueden causar que la CPU pierda el estado guardado de la instrucción LL - cambios de contexto, vaciados de caché o cambios en la tabla de páginas, tal vez.
falsamente: sin razón aparente
De acuerdo con atomic
paquete atomic
javadoc:
Las clases atómicas también admiten el método weakCompareAndSet, que tiene una aplicabilidad limitada.
En algunas plataformas, la versión débil puede ser más eficiente que compare y establecer en el caso normal, pero difiere en que cualquier invocación dada del método weakCompareAndSet puede devolver falso falsamente (es decir, sin motivo aparente ).
Un retorno falso significa solo que la operación puede reintentarse si se desea, confiando en la garantía de que la invocación repetida cuando la variable contiene expectedValue y que ningún otro subproceso también intenta establecer la variable finalmente tendrá éxito.
(Tales fallas espúreas pueden deberse, por ejemplo, a los efectos de contención de memoria que no están relacionados con si los valores esperados y actuales son iguales).Además, weakCompareAndSet no proporciona garantías de pedido que generalmente se necesitan para el control de sincronización.
De acuerdo con este hilo , no es tanto por "hardware / SO", sino por el algoritmo subyacente utilizado por weakCompareAndSet:
weakCompareAndSet establece atómicamente el valor en el valor actualizado dado si el valor actual == el valor esperado . Puede fallar falsamente.
A diferencia de compareAndSet (), y otras operaciones en un AtomicX, la operación weakCompareAndSet () no crea ningún orden de happen -before antes .
Por lo tanto, el hecho de que un hilo vea una actualización de un AtomicX causada por un weakCompareAndSet no significa que esté sincronizado correctamente con las operaciones que ocurrieron antes del weakCompareAndSet ().
Probablemente no desee utilizar este método, sino que simplemente use compareAndSet; ya que hay pocos casos en que weakCompareAndSet sea más rápido que compare y establece, y hay una serie de casos en los que tratar de optimizar su código utilizando weakCompareAndSet en lugar de compareAndSet introducirá errores de sincronización sutiles y difíciles de reproducir en su código.
Nota sobre los pedidos realizados antes de :
El Modelo de memoria Java (JMM) define las condiciones bajo las cuales se garantiza que un hilo que lea una variable vea los resultados de una escritura en otro hilo.
El JMM define un orden en las operaciones de un programa llamado pasa antes.
Ocurre, antes de que los pedidos entre subprocesos solo se creen sincronizando en un bloqueo común o accediendo a una variable volátil común.
A falta de una orden de suceso antes de, la plataforma Java tiene gran libertad para retrasar o cambiar el orden en que las escrituras en un hilo se vuelven visibles para las lecturas de esa misma variable en otro.
Un buen caso de uso para weakCompareAndSet son los contadores de rendimiento: no hay necesidad de pedir, alta tasa de actualizaciones (por lo que el pedido duele en sistemas débilmente ordenados), pero no descarta los conteos bajo altas cargas (contadores de rendimiento muy contentos pueden caer el 99% de todos cuenta, esencialmente dejando el valor de los contadores en relación con los contadores no contendientes al azar).