01 | Visibilidad, atomicidad y ordenamiento: la fuente de errores de programación concurrentes
La historia detrás del programa concurrente
Una de las fuentes: problemas de visibilidad causados por el almacenamiento en caché
La segunda fuente: el problema atómico causado por el cambio de hilo
La tercera fuente: el problema de pedidos provocado por la optimización de compilación
Resumen
02 | Modelo de memoria Java: vea cómo Java resuelve los problemas de visibilidad y orden
¿Qué es el modelo de memoria Java?
Confusión sobre el uso de volátiles
La regla sucede antes
El resultado de la operación anterior es visible para las operaciones posteriores.
-
La regla de secuencia del programa
Esta regla se refiere a la operación anterior Sucede antes en cualquier subproceso de acuerdo con la secuencia del programa en un subproceso. -
Regla de variable volátil
Esta regla se refiere a la operación de escritura de una variable volátil, sucede antes en la operación de lectura posterior de esta variable volátil. -
Transitividad
Esta regla significa que si A sucede antes que B y B sucede antes de C, entonces A sucede antes de C. -
La regla de bloqueo en el proceso de tubería
Esta regla se refiere al desbloqueo de un bloqueo que sucede antes y al bloqueo posterior de este bloqueo. -
Regla de inicio de subproceso ()
Se trata del inicio de subproceso. Significa que después de que el hilo principal A inicia el hilo secundario B, el hilo secundario B puede ver el funcionamiento del hilo principal antes de comenzar el hilo secundario B. -
Thread join () rule
Esto se trata de hilos en espera. Significa que el subproceso principal A espera a que se complete el subproceso B (el subproceso principal A se realiza llamando al método join () del subproceso B). Cuando se completa el subproceso B (el subproceso principal A regresa en el método join ()), el subproceso principal puede ver Al hilo hijo. Por supuesto, el llamado "ver" se refiere a la operación de variables compartidas.
Resumen
En el lenguaje Java,La semántica de Happens-Before es esencialmente un tipo de visibilidad., A sucede antes de B significa que el evento A es visible para el evento B, independientemente de si el evento A y el evento B ocurren en el mismo hilo. Por ejemplo, el evento A ocurre en el subproceso 1 y el evento B ocurre en el subproceso 2. La regla Sucede antes garantiza que el subproceso 2 también puede ver la ocurrencia del evento A.
03 | Bloqueo de exclusión mutua (Parte 1): Solución de problemas atómicos
¿Cómo resolver el problema atómico?
Ya sabe que la fuente del problema de atomicidad es
que la condición de cambio de subproceso "se ejecuta solo un subproceso al mismo tiempo" es muy importante, lo que llamamos exclusión mutua.
Modelo de bloqueo simple
Modelo de bloqueo mejorado
Tecnología de bloqueo proporcionada por el lenguaje Java: sincronizado
04 | Bloqueo de exclusión mutua (Parte 2): ¿Cómo proteger múltiples recursos con un solo bloqueo?
Proteja múltiples recursos que no están relacionados
Proteja múltiples recursos relacionados
Resumen
¿Cuál es la esencia de la "atomicidad"?? De hecho, no es indivisible, indivisible es solo una manifestación externa, su esencia es el requisito de coherencia entre múltiples recursos,El estado intermedio de la operación no es visible para el mundo exterior.
05 | ¿Qué hacer si me estanco accidentalmente?
Cómo prevenir un punto muerto
- Destruir las condiciones de ocupación y espera.
- Destrucción de condiciones no preferentes
- Romper la condición de espera de bucle
06 | Espera circular optimizada con mecanismo de "espera-notificación"
Implementación de mecanismo de notificación de espera con sincronización
07 | Problemas de seguridad, actividad y rendimiento
¿Es necesario analizar cuidadosamente todo el código si existen estos tres problemas? Por supuesto que no. De hecho, solo se necesita una situación: hay datos compartidos y los datos cambiarán. En términos generales, múltiples hilos leerán y escribirán los mismos datos al mismo tiempo.
Programación concurrenteHay muchos problemas a los que debemos prestar atención. Afortunadamente, nuestros predecesores nos han ayudado a resumirlos. Hay tres aspectos principales, a saber: problemas de seguridad, problemas activos y problemas de rendimiento.
Problemas de seguridad
Cuando varios subprocesos acceden a los mismos datos al mismo tiempo, y al menos un subproceso escribirá estos datos, si no tomamos medidas de protección, dará lugar a errores concurrentes. También hay un término profesional para esto, llamado carrera de datos (Carrera de datos) )
La condición de carrera se refiere al orden en que el resultado de la ejecución del programa depende de la ejecución del hilo.
Ante la competencia de datos y las condiciones de carrera , ¿cómo podemos garantizar la seguridad del hilo? De hecho, ambos tipos de problemas pueden usar la solución de tecnología de exclusión mutua, y existen muchas soluciones para lograr la exclusión mutua. La CPU proporciona instrucciones relacionadas mutuamente excluyentes, y el sistema operativo y el lenguaje de programación también proporcionan API relacionadas. Desde un punto de vista lógico, podemos unificarnos en: bloqueo .
Problema activo
El llamado problema de la vida se refiere a que no se puede realizar una operación. Nuestro "punto muerto" común es un problema activo típico, por supuesto, además del punto muerto , hay dos casos, a saber, " livelock " y "hambre" .
A veces, aunque el subproceso no está bloqueado, seguirá habiendo situaciones en las que no se puede ejecutar. Esto se denomina "bloqueo en vivo".
El llamado "hambre" se refiere a la situación que el hilo no puede ejecutarse porque no puede acceder a los recursos necesarios.
Problemas de rendimiento
La razón por la cual hay tantas cosas en el paquete concurrente de Java SDK es que una gran parte de la razón es mejorar el rendimiento en un campo específico.
Resumen
08 | Governance: la clave maestra para la programación concurrente
¿Qué es el control?
Modelo MESA
La postura correcta de esperar ()
notifique () cuándo se puede usar
Resumen
09 | Java Thread (Parte 1): Ciclo de vida de Java Thread
Ciclo de vida de hilo común
Subproceso de ciclo de vida en Java
-
Transición de estado RUNNABLE y BLOCKED
Solo hay un escenario que desencadenará esta transición, es decir, el subproceso espera un bloqueo implícito sincronizado -
La transición de estado de RUNNABLE and WAITING El
primer escenario es obtener un hilo de bloqueo implícito sincronizado y llamar al método Object.wait () sin parámetros.
El segundo escenario es llamar al método Thread.join () sin parámetros.
En el tercer escenario, llame al método LockSupport.park (). Llame al método LockSupport.park (), el subproceso actual se bloqueará y el estado del subproceso cambiará de EJECUTABLE a ESPERA. Llame a LockSupport.unpark (subproceso de subproceso) para activar el subproceso de destino, y el estado del subproceso de destino cambiará del estado ESPERA a EJECUTAR. -
Transición de estado RUNNABLE y TIMED_WAITING
-
Del estado NUEVO al EJECUTIVO, llame al método start () del objeto de subproceso
-
De RUNNABLE a estado TERMINADO
¿Cuál es la principal diferencia entre los métodos stop () e interrupt ()?
10 | Subprocesos Java (medio): ¿Cuántos subprocesos son apropiados para crear?
¿Por qué usar multithreading?
Hay muchos indicadores para medir el rendimiento, pero hay dos indicadores en el núcleo, que son la latencia y el rendimiento .
Escenarios de aplicaciones multiproceso
¿Cuántos hilos son apropiados para crear?
Los escenarios informáticos intensivos en CPU, en teoría, "el número de subprocesos = el número de núcleos de CPU" es el más apropiado. Sin embargo, en ingeniería, el número de subprocesos generalmente se establece en "núcleos de CPU + 1"
Para escenarios informáticos intensivos de E / S, el número óptimo de subprocesos = número de núcleos de CPU * [1 + (E / S que consume mucho tiempo / CPU)]
De hecho, siempre que comprenda un principio, este principio es maximizar el rendimiento del hardware.
11 | Java Threads (Parte 2): ¿Por qué las variables locales son seguras para subprocesos?
Cómo se ejecuta el método
¿Dónde se almacenan las variables locales?
Call stack and thread
Cierre de hilo
12 | ¿Cómo escribir programas concurrentes con pensamiento orientado a objetos?
Primero, encapsular variables compartidas
Para estas variables compartidas que no cambiarán, se recomienda que utilice la palabra clave final para modificar
Segundo, identifique las restricciones entre las variables compartidas.
3. Desarrollar estrategias de acceso concurrente
13 | Respuestas a temas candentes de los módulos de base teórica
¿Qué pasa con esta "historia en serie"?