objetos memoria liberar guardar collector java volatile thread-synchronization java-memory-model happens-before

liberar - Modelo de memoria Java: variables volátiles y sucede antes



java garbage collector (3)

Todas las acciones de sincronización (volátil w / r, bloqueo / desbloqueo, etc.) forman un orden total. [1] Esa es una declaración muy fuerte; hace el análisis más fácil. Para su v volátil, leer es antes de escribir, o escribir es antes de leer, en este orden total. El orden depende de la ejecución real del curso.

De ese orden total, podemos establecer pedidos parciales que suceda antes . [2] Si todas las lecturas y escrituras en una variable (volátil o no) se encuentran en una cadena de orden parcial, es fácil de analizar: una lectura ve la escritura inmediata anterior. Ese es el punto principal de JMM: establecer pedidos de lectura / escritura para que puedan razonarse como una ejecución secuencial.

Pero, ¿y si la lectura volátil es anterior a la escritura volátil? Necesitamos otra restricción crucial aquí: la lectura no debe ver la escritura. [3]

Por lo tanto, podemos razonar eso,

  1. read of v ve 0 (valor inicial) o 2 (escritura volátil)
  2. si ve 2, debe ser el caso de que la lectura sea posterior a la escritura; y en ese caso, tenemos happens-before cadena.

Último punto: lee de que debo ver una de las escrituras para i ; en este ejemplo, 0 o 1. Nunca verá un valor mágico de ninguna escritura.

citando la especificación java8:

[1] http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.4

[2] http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5

[3] http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.7

pensamientos aleatorios sobre el orden total:

Debido a este orden total, podríamos decir que una acción de sincronización ocurre antes que otra como a tiempo . Ese tiempo puede no corresponder al reloj de pared, pero no es un mal modelo mental para nuestro entendimiento. (En realidad, una acción en Java corresponde a una tormenta de actividades de hardware, es imposible definir un punto a tiempo para ello)

E incluso el tiempo físico no es absoluto. Recuerde que la luz viaja 30cm en 1ns; en las CPU actuales, el orden temporal es definitivamente relativo. El orden total realmente requiere que haya causalidad de una acción a la siguiente. Ese es un requisito muy fuerte, y usted apuesta a que JVM se esfuerza por optimizarlo.

Me gustaría aclarar cómo sucede, antes de que la relación funcione con variables volátiles . Vamos a tener las siguientes variables:

public static int i, iDst, vDst; public static volatile int v;

y el hilo A:

i = 1; v = 2;

y el hilo B:

vDst = v; iDst = i;

¿Las siguientes afirmaciones son correctas de acuerdo con el modelo de memoria de Java (JMM)? Si no, ¿cuál sería la interpretación correcta?

  • i = 1 siempre sucede, antes v = 2
  • v = 2 sucede antes que vDst = v en JMM solo si en realidad sucede antes en el tiempo
  • i = 1 sucede, antes de iDst = i en JMM (e iDst se asignará predeciblemente 1 ) si v = 2 sucede realmente antes de vDst = v en el tiempo
  • De lo contrario, el orden entre i = 1 e iDst = i no está definido y el valor resultante de iDst está definido.

Error en la lógica:

No hay un concepto de "tiempo de reloj de pared" en JMM, y debemos confiar en el orden de sincronización como una guía de ordenamiento para v = 2 y vDst = v . Vea la respuesta elegida para más detalles.


Sí, todos ellos son correctos de acuerdo con esta sección sobre el orden de suceso anterior:

  1. i = 1 siempre ocurre, antes v = 2 ya que:

Si xey son acciones del mismo hilo yx viene antes de y en el orden del programa, entonces hb (x, y) .

  1. v = 2 sucede antes que vDst = v en JMM solo si en realidad sucede antes en el tiempo, ya que v es volátil y

Una escritura en un campo volátil (§8.3.1.4) ocurre, antes de cada lectura posterior de ese campo.

  1. i = 1 sucede, antes de iDst = i en JMM (e iDst se asignará predeciblemente 1) si v = 2 realmente sucede antes de vDst = v en el tiempo. Esto se debe a que en este caso:
    • i = 1 pasa, antes v = 2
    • v = 2 sucede antes de vDst = v
    • vDst = v sucede antes de iDst = i

Si hb (x, y) y hb (y, z) , entonces hb (x, z) .

EDITAR:

Como argumentó @ user2357112, parece que las declaraciones 2 y 3 no son exactamente correctas. La relación de pasar antes de que ocurra no necesariamente impone un orden de tiempo entre las acciones que tienen esta relación, como se menciona en la misma sección de JLS:

Cabe señalar que la presencia de una relación de pase antes de dos acciones no implica necesariamente que tengan que tener lugar en ese orden en una implementación. Si el reordenamiento produce resultados consistentes con una ejecución legal, no es ilegal.

Por lo tanto, en términos de las reglas mencionadas en el JLS, no debemos hacer suposiciones sobre el momento real de la ejecución de las declaraciones.


  • i = 1 siempre sucede, antes v = 2

Cierto. Por JLS sección 17.4.5 ,

Si xey son acciones del mismo hilo yx viene antes de y en el orden del programa, entonces hb (x, y) .

  • v = 2 sucede antes que vDst = v en JMM solo si en realidad sucede antes en el tiempo
  • i = 1 sucede, antes de iDst = i en JMM (e iDst se asignará predeciblemente 1 ) si v = 2 sucede realmente antes de vDst = v en el tiempo

Falso. El orden de pasar antes de que ocurra no garantiza que las cosas suceden unas a otras en tiempo físico. De la misma sección de JLS,

Cabe señalar que la presencia de una relación de pase antes de dos acciones no implica necesariamente que tengan que tener lugar en ese orden en una implementación. Si el reordenamiento produce resultados consistentes con una ejecución legal, no es ilegal.

Sin embargo, se garantiza que v = 2 ocurre antes de que vDst = v i = 1 ocurra antes de que iDst = i si v = 2 viene antes de vDst = v en el orden de sincronización, un orden total sobre las acciones de sincronización de una ejecución eso a menudo se confunde con el orden en tiempo real.

  • De lo contrario, el orden entre i = 1 e iDst = i no está definido y el valor resultante de iDst está definido.

Este es el caso si vDst = v viene antes de v = 2 en el orden de sincronización, pero el tiempo real no entra.