thread practice example concurrent java multithreading concurrency java-memory-model

practice - Instrucción de reordenamiento y relación de sucede antes en java



java thread pool (1)

Esta pregunta ya tiene una respuesta aquí:

En el libro Java Concurrency In Practice, se nos dice varias veces que las instrucciones de nuestro programa pueden ser reordenadas, ya sea por el compilador, por la JVM en tiempo de ejecución o incluso por el procesador. Por lo tanto, debemos suponer que el programa ejecutado no tendrá sus instrucciones ejecutadas exactamente en el mismo orden que el especificado en el código fuente.

Sin embargo, el último capítulo sobre el Modelo de memoria de Java proporciona una lista de las reglas de pasar antes que indican qué orden de instrucciones conserva la JVM. La primera de estas reglas es:

  • "Regla de orden de programa. Cada acción en un hilo ocurre antes de cada acción en ese hilo que viene más tarde en el orden del programa".

Creo que el "orden del programa" se refiere al código fuente.

Mi pregunta : asumiendo esta regla, me pregunto qué instrucción se puede reordenar realmente.

"Acción" se define de la siguiente manera:

El modelo de memoria de Java se especifica en términos de acciones, que incluyen lecturas y escrituras en variables, bloqueos y desbloqueos de monitores, y el inicio y la unión con hilos. El JMM define un orden parcial llamado anteriormente en todas las acciones dentro del programa. Para garantizar que la acción de ejecución de subprocesos B pueda ver los resultados de la acción A (independientemente de si A y B se producen en diferentes subprocesos), debe haber un suceso antes de la relación entre A y B. En ausencia de un suceso antes de ordenar entre dos operaciones, la JVM es libre de reordenarlos como lo desee.

Otras reglas de orden mencionadas son:

  • Regla de bloqueo del monitor. Un desbloqueo en un bloqueo de monitor ocurre antes de cada bloqueo posterior en ese mismo bloqueo de monitor.
  • Regla de variable volátil Una escritura en un campo volátil ocurre antes de cada lectura posterior de ese mismo campo.
  • Regla de inicio del hilo. Una llamada a Thread.start en un hilo ocurre antes de cada acción en el hilo iniciado.
  • Regla de terminación de hilo. Cualquier acción en un hilo ocurre antes de que cualquier otro hilo detecte que el hilo ha terminado, ya sea devolviéndola correctamente desde Thread.join o por Thread.isAlive devolviendo el mensaje falso.
  • Regla de interrupción Se produce una interrupción de llamada de subproceso en otro subproceso antes de que el subproceso interrumpido detecte la interrupción (ya sea que se interrumpa InterruptedException o se interrumpa o interrumpa).
  • Regla del finalizador El final de un constructor para un objeto ocurre antes del inicio del finalizador para ese objeto.
  • Transitividad Si A ocurre antes de B, y B sucede antes de C, entonces A sucede antes de C.

El punto clave de la regla de orden del programa es: en un hilo .

Imagine este programa simple (todas las variables inicialmente 0):

T1:

x = 5; y = 6;

T2:

if (y == 6) System.out.println(x);

Desde la perspectiva de T1, una ejecución debe ser consistente con que se le asigne después de x (orden del programa). Sin embargo, desde la perspectiva de T2, este no tiene que ser el caso y T2 podría imprimir 0.

T1 está realmente permitido asignar y primero ya que las 2 asignaciones son independientes y su intercambio no afecta la ejecución de T1.

Con la sincronización adecuada, T2 siempre imprimirá 5 o nada.

EDITAR

Parece que estás malinterpretando el significado del orden del programa. La regla de orden del programa se reduce a :

Si y son acciones del mismo hilo y x viene antes de y en el orden del programa, entonces hb(x, y) (es decir, x sucede -antes de y ).

pasa-antes tiene un significado muy específico en el JMM. En particular, no significa que y=6 debe ser posterior a x=5 en T1 desde una perspectiva de reloj de pared. Solo significa que la secuencia de acciones ejecutadas por T1 debe ser coherente con ese orden. También puede consultar JLS 17.4.5 :

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.

En el ejemplo que di más arriba, estarán de acuerdo desde la perspectiva de T1 (es decir, en un único programa de subprocesos), x=5;y=6; es consistente con y=6;x=5; ya que no lee los valores Se garantiza una declaración en la siguiente línea, en T1, para ver esas 2 acciones, independientemente del orden en que se realizaron.