1. El concepto de proceso y hilo
(1) En los sistemas operativos tradicionales, los programas no pueden ejecutarse de forma independiente, y como las unidades básicas de asignación de recursos y operaciones independientes son todos procesos.
En los sistemas sin sistema operativo, el método de ejecución de los programas es una ejecución secuencial, es decir, un programa debe ejecutarse antes de que se pueda ejecutar otro programa; En un entorno de múltiples programas, se permite ejecutar múltiples programas simultáneamente. Existen diferencias significativas entre las dos formas de ejecución de un programa. Es precisamente esta característica de la ejecución concurrente de programas lo que conduce a la introducción del concepto de procesos en el sistema operativo.
Desde que las personas propusieron el concepto de procesos en la década de 1960, los procesos siempre se han utilizado en el sistema operativo como la unidad básica que puede tener recursos y funcionar de forma independiente. Hasta mediados de la década de 1980, las personas propusieron una unidad básica que puede ejecutarse de forma independiente, los hilos, que son más pequeños que los procesos, para tratar de usarla para aumentar el grado de ejecución concurrente de programas dentro del sistema, aumentando aún más el rendimiento del sistema. Especialmente después de ingresar a la década de 1990, los sistemas multiprocesador se han desarrollado rápidamente. Los hilos pueden mejorar mejor la ejecución paralela de programas que los procesos y ejercer completamente las ventajas de los multiprocesadores. Por lo tanto, se han introducido hilos en el sistema operativo multiprocesador lanzado en los últimos años para mejorar el rendimiento del sistema operativo.
"Lo anterior está extraído del " Sistema operativo de computadora, editado por Tang Xiaodan y otros - Edición 3 " (Dirección de descarga)
(2) La siguiente figura es una explicación de los usuarios de Zhihu:
A través de la comprensión general anterior, básicamente sabemos qué hilos y procesos hacen. Así que resumamos el concepto de procesos y hilos a continuación:
(3) El proceso es una actividad en ejecución de un programa en una computadora sobre un determinado conjunto de datos, es la unidad básica de la asignación y programación de recursos del sistema, y es la base de la estructura del sistema operativo. En las primeras estructuras informáticas orientadas al proceso, los procesos fueron las entidades de ejecución básicas de los programas; En las estructuras informáticas contemporáneas orientadas a los hilos, los procesos eran contenedores de hilos. Un programa es una descripción de las instrucciones, los datos y su forma organizativa, y un proceso es una entidad de un programa.
(4) Los hilos, a veces llamados procesos livianos (LWP), son la unidad más pequeña de flujo de ejecución del programa. Los hilos son un solo proceso de control secuencial en un programa. Una unidad de ejecución relativamente independiente y programable en el proceso es la unidad básica de programación y envío de CPU independientes en el sistema, que se refiere a la unidad de programación de programas en ejecución. Ejecutar múltiples hilos simultáneamente en un solo programa para completar diferentes trabajos, llamado multithreading.
(5) La relación entre el proceso y el hilo:
2. Java implementa el método de múltiples subprocesos
(1) heredar hilo y reescribir el método run ()
Public Class MyThread extiende el hilo {@Override public void run () {while (true) {system.out.println (this.currentThread (). getName ()); }} public static void main (string [] args) {myThread Thread = new MyThread (); Thread.Start (); // La forma correcta de iniciar el hilo}}Resultado de salida:
Thread-0thread-0Thread-0 ...
Además, debe comprender que el método Start () es el método Start () en lugar del método run (). Si se usa el método run (), entonces es un método ordinario para ejecutar.
(2) Implementar la interfaz ejecutable
Public Class Myrunnable Implements Runnable {@Override public void run () {System.out.println ("123"); } public static void main (string [] args) {myrunnable myrunnable = new Myrunnable (); Hilo de hilo = nuevo hilo (myrunnable, "t1"); Thread.Start (); }}3. Seguridad del hilo
Concepto de seguridad de hilos: cuando múltiples subprocesos acceden a una determinada clase (objeto o método), la clase siempre puede mostrar el comportamiento correcto, y luego esta clase (objeto o método) es segura.
La seguridad del hilo es cuando se accede a múltiples hilos, se adopta un mecanismo de bloqueo. Cuando un hilo accede a ciertos datos de la clase, está protegido. Otros hilos no pueden acceder a él hasta que el hilo haya terminado de leerlo, y otros hilos no pueden usarlo. No habrá inconsistencia de datos ni contaminación de datos. Los hilos no son seguros, lo que significa que no proporcionan protección de acceso a datos. Es posible que múltiples hilos puedan cambiar los datos uno tras otro, lo que resulta en que los datos resultantes estén sucios. El mecanismo de bloqueo común aquí es: sincronizado
4. Modificador sincronizado
(1) Sincronizado: puede agregar bloqueos a cualquier objeto y método, y el código bloqueado se llama "área mutex" o "área crítica".
(2) ** No use ** instancia sincronizada (código a):
public class myThread extiende hilo {private int count = 5; @Override public void run () {count-; system.out.println (this.currentThread (). getName () + "count:" + count);} public static void main (string [] args) {mythread mythread = new myThread (); hilo hilo de hilo1 = new thhushad, hilo de hilo de hilo); hilo de hilo de hilo); hilo de hilo de hilo); hilo de hilo de hilo); hilo de hilo. Thread (myThread, "Thread2"); Thread Thread3 = New Thread (MyThread, "Thread3"); Thread Thread4 = New Thread (MyThread, "Thread4"); Thread Thread5 = New Thread (MyThread, "Thread5"); Thread1.Start (); Thread2.Start (); Subt3.Start (); Thread4.Start (); Thread5.start ();}}}}}}}}}Un resultado de la salida es el siguiente:
THRESP3 Recuento: 2Thread4 Conde: 1Thread1 Conde: 2Thread2 Conde: 3Thread5 Conde: 0
Se puede ver que el resultado anterior es incorrecto, porque múltiples subprocesos operan el método run () al mismo tiempo y modifican el recuento, que a su vez causa un error.
(3) ** use ** instancia sincronizada (código b):
Public Class MyThread extiende Thread {private int count = 5; @Override public Synchronized void run () {Count--; System.out.println (this.CurrentThread (). GetName () + "Count:" + Count); } public static void main (string [] args) {mythread mythread = new MyThread (); Thread Thread1 = New Thread (MyThread, "Thread1"); Thread Thread2 = New Thread (MyThread, "Thread2"); Thread Thread3 = New Thread (MyThread, "Thread3"); Thread Thread4 = New Thread (MyThread, "Thread4"); Thread Thread5 = New Thread (MyThread, "Thread5"); Thread1.Start (); thread2.start (); thread3.start (); Thread4.Start (); Thread5.Start (); }}Resultado de salida:
hilo1 recuento: 4Thread2 recuento: 3Thread3 recuento: 2Tread5 recuento: 1Tread4 recuento: 0
Se puede ver que la diferencia entre el código A y el código B es que se agrega modificación sincronizada al método run ().
La descripción es la siguiente:
Cuando múltiples hilos acceden al método de ejecución myThread, si se usa modificación sincronizada, el subproceso múltiple se procesará en una cola (la cola aquí se determina de acuerdo con el orden de la asignación de CPU). Si un hilo quiere ejecutar el código en el método de modificación sincronizado, primero intenta obtener el bloqueo. Si obtiene el bloqueo, ejecuta el contenido del cuerpo del código sincronizado. Si no puede obtener el bloqueo, el hilo continuará tratando de obtener el bloqueo hasta que lo obtenga. Además, múltiples hilos compiten por el bloqueo al mismo tiempo, lo que significa que se producirá la competencia de bloqueo.
5. ¡Un objeto tiene un bloqueo! ¡Múltiples hilos y múltiples bloqueos!
¡Qué es, un objeto tiene un bloqueo, múltiples hilos tienen múltiples bloqueos! Primero, echemos un vistazo al código de ejemplo a continuación (Código C):
clase pública multithithread {private int num = 200; public sincronizado void printnum (string threadname, etiqueta de cadena) {if (tag.equals ("a")) {num = num - 100; System.out.println (ThreadName + "Etiqueta A, Establezca Num sobre!"); } else {num = num - 200; System.out.println (ThreadName + "Tag" + Tag + ", num =" + num); } public static void main (string [] args) lanza interruptedException {final múltiple multithithread1 = new Multithread (); final múltiple multithithread2 = new múltiple (); new Thread (new Runnable () {public void run () {multithithread1.printnum ("hilo1", "a");}}). start (); Thread.sleep (5000); System.out.println ("¡Espere 5 segundos para asegurarse de que Thread1 haya sido ejecutado!"); new Thread (new runnable () {public void run () {multithread2.printnum ("hilo2", "b");}}). start (); }}Resultado de salida:
Thread1 Etiqueta A, Establezca Num Over! Thread1 Etiqueta A, Num = 100Wait 5 segundos para asegurarse de que Thread1 haya sido ejecutado! TAGET2 Etiqueta B, Establezca Num sobre! Tag2 Tag B, num = 0
Se puede ver que hay dos objetos: multithread1 y multithithread2. Si múltiples objetos usan el mismo bloqueo, el resultado de la ejecución anterior debe ser: Tag2 Tag B, num = -100. Por lo tanto, cada objeto tiene el bloqueo de ese objeto.
Los bloqueos obtenidos por la palabra clave sincronizada son bloqueos de objetos, en lugar de tratar un código o método como bloqueos. Por lo tanto, en el código de ejemplo anterior C, que hilo ejecuta primero el método de palabras clave sincronizado, el subproceso contiene el bloqueo del objeto al que pertenece el método. El hilo obtiene dos cerraduras diferentes de dos objetos diferentes, y se complementan entre sí.
Entonces, en escenarios normales, debe haber una situación en la que todos los objetos operen en un recuento de variables, entonces, ¿cómo implementarlo? Es muy simple agregar estático. Sabemos que todos los objetos en esta clase tienen la misma referencia, sin importar cuántos objetos estén instanciados, la llamada es un método, y el código es el siguiente (Código D):
clase pública multithithread {private static int num = 200; public static sincronizado void printnum (string threadname, etiqueta de cadena) {if (tag.equals ("a")) {num = num - 100; System.out.println (ThreadName + "Etiqueta A, Establezca Num sobre!"); } else {num = num - 200; System.out.println (ThreadName + "Etiqueta B, Establezca NUM!"); } System.out.println (ThreadName + "Tag" + Tag + ", num =" + num); } public static void main (string [] args) lanza interruptedException {final múltiple multithithread1 = new Multithread (); final múltiple multithithread2 = new múltiple (); new Thread (new Runnable () {public void run () {multithithread1.printnum ("hilo1", "a");}}). start (); Thread.sleep (5000); System.out.println ("¡Espere 5 segundos para asegurarse de que Thread1 haya sido ejecutado!"); new Thread (new runnable () {public void run () {multithread2.printnum ("hilo2", "b");}}). start (); }}Resultado de salida:
Thread1 Etiqueta A, Establezca Num Over! Thread1 Etiqueta A, Num = 100Wait 5 segundos para asegurarse de que Thread1 haya sido ejecutado! TAGET2 Etiqueta B, Establezca Num sobre! Tag de Thread2 B, num = -100
Se puede ver que agregar modificación estática a variables y métodos puede obtener los escenarios que necesitamos. También muestra que para los métodos o variables de modificación estática no estática, un objeto bloqueado.
6. Locos de objetos sincrónicos y asincrónicos
(1) Sincronizado
El concepto de sincronización es compartir. Necesitamos saber que la palabra "compartir" no es un recurso compartido, no hay necesidad de sincronizar, es decir, no hay necesidad de bloquearla;
El propósito de la sincronización es garantizar la seguridad de los subprocesos. De hecho, para la seguridad del hilo, se deben cumplir dos características más básicas: atomicidad y visibilidad;
(2) Asincronizado: asincronizado
El concepto de asíncrona es la independencia, sin ninguna restricción entre sí, y no hay relación entre los dos.
(3) Código de muestra:
clase pública myObject {public void Method () {System.out.println (Thread.CurrentThread (). getName ()); } public static void main (string [] args) {final myObject myObject = new myObject (); Thread t1 = new Thread (new runnable () {public void run () {myObject.method ();}}, "t1"); Thread t2 = new Thread (new runnable () {public void run () {myObject.method ();}}, "t2"); t1.start (); t2.start (); }}En el código anterior, el método () es un método asincrónico.
Resumir
Lo anterior es todo el contenido de este artículo sobre la solución inicial al concepto de subprocesos, procesos y sincronizado en Java Multi-Threading. Espero que sea útil para todos. Si hay deficiencias, deje un mensaje y lo indique, y el editor responderá a todos a tiempo.