Entrevista | Cambio de contexto en multiproceso

Haga clic para seguir "Hometown Learn Java"

"Establecer como estrella" en la esquina superior derecha

Más de un mes antes de Double Eleven, todos los sistemas relacionados con el comercio electrónico se someten a pruebas de estrés y optimización continua del sistema. Nuestro sistema ERP de comercio electrónico también se ha sometido a pruebas de estrés y optimización durante más de un mes. , Encontramos una gran cantidad de alarmas de tiempo de espera. A través del análisis de herramientas, encontramos que el indicador cs era muy alto, y luego analizamos el registro, encontramos que había una gran cantidad de Excepciones relacionadas con wait (). En este momento, sospechamos que ocurría durante el procesamiento concurrente de múltiples subprocesos. Una gran cantidad de subprocesos no resolvió estos problemas a tiempo. Más tarde, al reducir el número máximo de subprocesos en el grupo de subprocesos y luego realizar pruebas de estrés, encontramos que el rendimiento del sistema ha mejorado.

Todos sabemos que en la programación concurrente, cuantos más subprocesos, mayor será la eficiencia. Demasiados subprocesos pueden llevar a una utilización insuficiente de recursos, demasiados subprocesos pueden conducir a una feroz competencia por los recursos, y luego el cambio frecuente de contexto provocará una sobrecarga adicional del sistema.

¿Qué es el cambio de contexto?


Todos sabemos que al procesar tareas simultáneas de subprocesos múltiples, el procesador asignará porciones de tiempo de CPU a cada subproceso. Los subprocesos ejecutan tareas en sus porciones de tiempo asignadas. El tamaño de cada porción de tiempo es generalmente de decenas de milisegundos, por lo que en Puede haber decenas o cientos de hilos que se intercambian en un segundo, lo que nos da la sensación de que están sucediendo al mismo tiempo.

Un subproceso solo ocupa el procesador en el intervalo de tiempo asignado. Cuando se agota el intervalo de tiempo asignado de un subproceso, o cuando se ve obligado a suspender la operación por sus propias razones, otro subproceso ocupará el procesador. Este tipo de subproceso se da por vencido El proceso de los derechos de uso del procesador y otro subproceso que obtiene los derechos de uso del procesador se denomina cambio de contexto.

Cuando un subproceso renuncia al derecho de usar el procesador, se "corta", otro subproceso obtiene el derecho de usar el procesador. Se "corta". En el proceso de entrada y salida, el sistema operativo guardará y restaurará la información de progreso relacionada. Esta información de progreso es lo que a menudo llamamos "contexto", que generalmente incluye el contenido de almacenamiento de registros y el almacenamiento de contadores de programas. El contenido de la instrucción.

Razones para el cambio de contexto


En la programación de subprocesos múltiples, sabemos que el cambio de contexto entre subprocesos puede causar problemas de rendimiento, entonces, ¿qué causa el cambio de contexto entre subprocesos? Primero echemos un vistazo al ciclo de vida de un hilo y miremos para encontrar la respuesta.

Tenemos muy claro los cinco estados de los subprocesos: NUEVO, RUNNABLE, RUNNING, BLOCKED y DEAD. Los seis estados correspondientes en Java son: NEW, RUNABLE, BLOCKED, WAINTING, TIMED_WAITING y TERMINADTED.

En la figura, el proceso de un hilo de RUNNABLE a RUNNING es el cambio de contexto del hilo. El proceso del estado RUNNING a BLOCKED, luego a RUNNABLE, y luego de RUNNABLE a RUNNING es un proceso de cambio de contexto. Cuando un subproceso pasa del estado EN EJECUCIÓN a BLOQUEADO, lo llamamos suspensión del subproceso. Cuando se suspende el subproceso, el procesador estará ocupado por otros subprocesos y el sistema operativo guardará el contexto correspondiente, de modo que este subproceso ingresará al estado RUNNABLE en el futuro. Puede continuar la ejecución desde el progreso de ejecución anterior. Cuando el hilo ingresa a RUNNABLE desde el estado BLOQUEADO, es decir, el hilo se despierta, en este momento el hilo obtendrá la última información de contexto guardada.

Vemos que el cambio de contexto del subproceso múltiple en realidad es causado por el cambio mutuo de los dos estados de ejecución del subproceso múltiple.

Sabemos que dos situaciones pueden causar un cambio de contexto: una es el cambio desencadenado por el programa en sí, que generalmente llamamos cambio de contexto espontáneo, y la otra es el cambio de contexto causado por el sistema o máquina virtual, que llamamos no espontáneo Cambio de contexto.

El contexto espontáneo es que el hilo es cortado por la llamada del programa Java. Generalmente, al codificar, se llaman los siguientes métodos o palabras clave:

sleep()
wait()
yield()
join()
park();
synchronized
lock

El cambio de contexto no espontáneo es común: el segmento de tiempo asignado al subproceso se agota, debido a la recolección de basura de la máquina virtual o debido a problemas de prioridad de ejecución.

Pequeña prueba encontrada cambio de contexto


Tomemos un ejemplo para ver la comparación de velocidades entre la ejecución concurrente y la ejecución en serie;


public class DemoApplication {
       public static void main(String[] args) {
              //运行多线程
              MultiThreadTester test1 = new MultiThreadTester();
              test1.Start();
              //运行单线程
              SerialTester test2 = new SerialTester();
              test2.Start();
       }
       
       
       static class MultiThreadTester extends ThreadContextSwitchTester {
              @Override
              public void Start() {
                     long start = System.currentTimeMillis();
                     MyRunnable myRunnable1 = new MyRunnable();
                     Thread[] threads = new Thread[4];
                     //创建多个线程
                     for (int i = 0; i < 4; i++) {
                           threads[i] = new Thread(myRunnable1);
                           threads[i].start();
                     }
                     for (int i = 0; i < 4; i++) {
                           try {
                                  //等待一起运行完
                                  threads[i].join();
                           } catch (InterruptedException e) {
                                  // TODO Auto-generated catch block
                                  e.printStackTrace();
                           }
                     }
                     long end = System.currentTimeMillis();
                     System.out.println("multi thread exce time: " + (end - start) + "s");
                     System.out.println("counter: " + counter);
              }
              // 创建一个实现Runnable的类
              class MyRunnable implements Runnable {
                     public void run() {
                           while (counter < 100000000) {
                                  synchronized (this) {
                                         if(counter < 100000000) {
                                                increaseCounter();
                                         }
                                         
                                  }
                           }
                     }
              }
       }
       
      //创建一个单线程
       static class SerialTester extends ThreadContextSwitchTester{
              @Override
              public void Start() {
                     long start = System.currentTimeMillis();
                     for (long i = 0; i < count; i++) {
                           increaseCounter();
                     }
                     long end = System.currentTimeMillis();
                     System.out.println("serial exec time: " + (end - start) + "s");
                     System.out.println("counter: " + counter);
              }
       }

       //父类
       static abstract class ThreadContextSwitchTester {
              public static final int count = 100000000;
              public volatile int counter = 0;
              public int getCount() {
                     return this.counter;
              }
              public void increaseCounter() {
                     
                     this.counter += 1;
              }
              public abstract void Start();
       }
}

Resultados del;

multi thread exce time: 5149s
counter: 100000000
serial exec time: 956s
counter: 100000000

Mediante la comparación de los resultados de ejecución, podemos ver que la velocidad de ejecución en serie es más rápida que la velocidad de ejecución concurrente. Esto se debe a que el cambio de contexto de varios subprocesos provoca una sobrecarga adicional del sistema. El uso de la palabra clave sincronizada provoca competencia de bloqueo. Esto conduce a un cambio de contexto de subprocesos.Si la palabra clave sincronizada no se usa en este lugar, la eficiencia de la ejecución concurrente no es tan rápida como la velocidad de ejecución en serie, porque el cambio de contexto de múltiples subprocesos sin competencia de bloqueo todavía existe.

¿Qué enlace es la sobrecarga del sistema en el cambio de contexto?

  • Sistema operativo guardar y restaurar contexto

  • Carga de la caché del procesador

  • Programador

  • Vaciado de búfer de alta velocidad causado por cambio de contexto

para resumir


El contexto es una liberación del derecho a usar el procesador, y otro subproceso adquiere el derecho a usar el procesador. Las operaciones de invocación espontáneas y no espontáneas causarán cambios de contexto y una sobrecarga de recursos del sistema. Cuantos más subprocesos, más rápida será la velocidad de ejecución.Cuando la lógica única es relativamente simple y la velocidad es relativamente muy rápida, recomendamos utilizar un solo subproceso. Si la lógica es muy complicada, o donde se requieren muchos cálculos, recomendamos el uso de subprocesos múltiples para mejorar el rendimiento del sistema.

- FIN -

Charla pequeña: el clima es cada vez más frío, puedes seguir la cuenta oficial, puedes agregar mi cuenta personal de WeChat, llevarte al grupo de intercambio técnico y calentarnos juntos ~

Buena recomendación de artículo (haga clic para leer):

Hola a todos, soy el autor de "My Hometown Learn Java", pueden llamarme "Hometown".

Siempre creo que la tecnología puede cambiar la vida, estoy dispuesto a mantener mi intención original, y a los técnicos de reabastecimiento de combustible!

Supongo que te gusta

Origin blog.csdn.net/qq_38862257/article/details/109685644
Recomendado
Clasificación