1. Varios conceptos importantes sobre alta concurrencia
1.1 Síncrono y asincrónico
En primer lugar, la sincronización y la asincrónica mencionadas aquí se refieren a los aspectos de la llamada de la función/método.
Obviamente, una llamada sincrónica esperará que el método regrese, y una llamada asíncrona volverá al instante, pero una llamada asíncrona regresará instantáneamente no significa que su tarea se haya completado. Configurará un hilo en el fondo para continuar la tarea.
1.2 Concurrencia y paralelismo
La concurrencia y el paralelismo son similares en apariencia externa. Como se muestra en la figura, el paralelismo es cuando dos tareas se realizan simultáneamente, mientras que la concurrencia es hacer una tarea a la vez y luego cambiar a otra tarea. Por lo tanto, una sola CPU no puede ser paralela, solo puede ser concurrencia.
1.3 Zona crítica
El área crítica se utiliza para representar un recurso público o datos compartidos. Se puede usar mediante múltiples hilos, pero solo un hilo puede usarlo a la vez. Una vez que el recurso de área crítica está ocupada, otros hilos deben esperar si quieren usar este recurso.
1.4 Bloqueo y no bloqueo
El bloqueo y el no bloqueo generalmente describen la influencia mutua entre múltiples hilos. Por ejemplo, si un hilo ocupa el recurso de área crítica, entonces todos los demás hilos que necesitan este recurso deben esperar en esta área crítica, y esperar hará que el hilo cuelgue. Esto es un bloqueo. En este momento, si el hilo que ocupa el recurso no está dispuesto a liberar el recurso, entonces todos los demás hilos que bloquean en esta área crítica no pueden funcionar.
El no bloqueo permite que múltiples subprocesos ingresen a la zona crítica al mismo tiempo
Por lo tanto, el rendimiento del bloqueo generalmente no es muy bueno. Según las estadísticas generales, si un hilo se suspende a nivel del sistema operativo y ha hecho un interruptor de contexto, generalmente tarda 80,000 ciclos de tiempo en hacerlo.
1.5 Deadlock, hambre, bloqueo en vivo
El llamado punto muerto se refiere a un bloqueo causado por recursos competitivos o comunicándose entre sí durante el proceso de ejecución de dos o más procesos. Sin fuerzas externas, no podrán avanzar. En este momento, el sistema se llama estancado o el sistema tiene un punto muerto. Estos procesos que siempre se esperan unos a otros se llaman procesos de punto muerto. Al igual que los autos en la imagen a continuación quieren avanzar, pero nadie puede avanzar.
Sin embargo, aunque el punto muerto es un mal fenómeno, es un problema estático. Una vez que ocurre un punto muerto, el proceso está atascado y la tasa de ocupación de la CPU también es 0. No ocupará la CPU, se llamará. Relativamente hablando, es relativamente fácil de descubrir y analizar.
Correspondiente al punto muerto está el bloqueo vivo.
Live Lock significa que las cosas 1 pueden usar recursos, pero permite que otras cosas usen recursos primero; Las cosas 2 pueden usar recursos, pero también permite que otras cosas usen recursos primero, por lo que ambos han sido humildes y no pueden usar recursos.
Por ejemplo, es como si conocieras a alguien en la calle, que está caminando en la dirección opuesta a ti y te conoces de frente, todos quieren dejar que se vayan. Te moviste hacia la izquierda y él se movió hacia la izquierda, pero los dos todavía no podían ir allí. En este momento, te mueves hacia la derecha y él se mueve hacia la derecha, y continúa de esta manera.
Cuando un hilo obtiene un recurso, encuentra que otros hilos también piensan en este recurso porque no han obtenido todos los recursos, por lo que para evitar el matorral de muertos, renuncian a todos los recursos que tienen. Si otro hilo hace lo mismo, necesitan los mismos recursos, como A contiene un recurso, B tiene el recurso B, y después de renunciar al recurso, A obtiene el recurso B, y B obtiene un recurso, y esto se repite, se produce un bloqueo vivo.
Los bloqueos vivos son más difíciles de detectar que los puntos muertos, porque los bloqueos vivos son un proceso dinámico.
El hambre significa que uno o más hilos no pueden obtener los recursos requeridos por varias razones, lo que los hace incapaces de ejecutar.
1.6 Nivel de concurrencia
Niveles de concurrencia: bloqueo y no bloqueo (sin bloquear se divide en barreras sin barreras, sin cerraduras y sin espera)
1.6.1 Bloqueo
Cuando un hilo ingresa a la sección crítica, otros hilos deben esperar
1.6.2 Accesibilidad
En comparación con la programación sin bloqueo, la programación de bloqueo es una estrategia pesimista, que cree que modificar datos juntos es probable que los datos sean malos. En lugar de bloquear la programación, es una estrategia optimista, que cree que modificar los datos puede no necesariamente hacer que los datos fueran malos. Sin embargo, es una estrategia de entrada amplia y salida estricta. Cuando descubre que un proceso tiene competencia de datos y conflictos en el área crítica, el método de programación sin barreras retrasará los datos.
En este método de programación sin barreras, todos los hilos son equivalentes a tomar una instantánea de un sistema. Seguirán tratando de tomar las instantáneas hasta que sean válidas.
1.6.3 sin bloqueo
Es accesible
Asegúrese de que haya un hilo que pueda ganar
En comparación con la accesibilidad, la accesibilidad no garantiza que las operaciones se puedan completar cuando hay competencia, porque si encuentra conflictos en cada operación, seguirá intentando. Si los hilos en el área crítica interfieren entre sí, hará que todos los hilos se atasquen en el área crítica, y luego el rendimiento del sistema tendrá un gran impacto.
Lockless agrega una nueva condición para garantizar que un hilo pueda ganar cada competencia, lo que resuelve el problema de la frenilidad de barrera. Al menos asegura que todos los hilos se ejecuten sin problemas.
El siguiente código es un código de cálculo típico sin bloqueo en Java
Lockless es común en Java
while (! AtomiCVar.COMPareAndset (localVar, localVar+1)) {localVar = AtomicVar.get (); }1.6.4 No espera
Sin bloqueo
Todos los hilos deben completarse dentro de un paso limitado
Sin hambre
En primer lugar, la premisa de No Waiting se basa en sin bloqueo. Sin bloquear solo asegura que debe haber entrada y salida en el área crítica. Sin embargo, si la prioridad de entrada es muy alta, entonces algunos hilos con baja prioridad en el área crítica pueden tener hambre y no pueden abandonar el área crítica. Luego no hay espera para resolver este problema, lo que asegura que todos los hilos deben completarse dentro de un paso limitado, y naturalmente no hay hambre.
No esperar es el nivel más alto de paralelismo, lo que puede permitir que este sistema alcance el estado óptimo.
Casos típicos sin esperar:
Si solo hay hilos de lectura y sin hilos, entonces esto debe ser sin esperar.
Si hay hilos de lectura y hilos de escritura, y antes de cada subproceso de escritura, copie los datos y luego modifique la copia en lugar de modificar los datos originales, porque no hay conflicto en la modificación de la copia, entonces el proceso de modificación también es sin esperar. La sincronización final es solo sobrescribir los datos escritos.
Dado que el requisito libre de espera es relativamente alto y es difícil de implementar, el bloqueo sin bloqueo se usará más ampliamente.
2. Dos leyes importantes sobre el paralelismo
Ambas leyes están relacionadas con la relación de aceleración
2.1 Ley de Amdahl
Definir la fórmula de cálculo y el límite superior teórico de la relación de aceleración después de la paralelización de los sistemas en serie
Definición de la relación de aceleración: relación de aceleración = tiempo del sistema consumido antes de la optimización / tiempo del sistema consumido después de la optimización
Por ejemplo:
Ratio de aceleración = Tiempo del sistema consumido antes de la optimización / tiempo del sistema consumido después de la optimización = 500 /400 = 1.25
Este teorema muestra que aumentar el número de procesadores de CPU no necesariamente juega un papel efectivo en el aumento de la proporción de módulos paralelos en el sistema. Solo aumentando razonablemente el número de procesadores paralelos se puede obtener la relación de aceleración máxima con la inversión más pequeña.
2.2 Ley de Gustafson
Explicar la relación entre el número de procesadores, la relación en serie y la relación de aceleración
Entonces la relación de aceleración = nf (n-1) // se omite el proceso de derivación
Mientras haya suficiente paralelización, la relación de aceleración es proporcional al número de CPU.