En Java, la palabra clave sincronizada y el bloqueo de bloqueo se utilizan para realizar un control de acceso concurrente de los recursos. Solo los subprocesos únicos pueden ingresar al área crítica para acceder a recursos (excepto leer bloqueos). El objetivo principal de este subtrol es resolver el problema de la inconsistencia de los datos causado por múltiples hilos simultáneamente con el mismo recurso. En otro escenario, un recurso tiene múltiples copias para su uso al mismo tiempo, como múltiples impresoras en la sala de la impresora y múltiples pozos para usar al mismo tiempo. En este caso, Java proporciona otro control de acceso concurrente: control de acceso concurrente para múltiples copias del recurso, y el semáforo utilizado hoy en día es uno de ellos.
Java puede detectar posibles problemas de seguridad de los subprocesos en nuestro sistema de la manera más rápida a través de la simulación de código. Aquí, Semaphore (Semaphore) y CountdownLatch (bloqueo) se utilizan con EjecutorService (grupo de subprocesos) para la simulación. La introducción principal es la siguiente:
1. Semafore
Esta clase se proporcionará después de JDK 1.5
Semaphore es un semáforo basado en el conteo. Puede establecer un umbral, en función de esto, múltiples hilos compiten para obtener la señal de licencia y devolverla después de hacer su propia aplicación. Después de exceder el umbral, se bloqueará la aplicación del hilo para la señal de licencia. Semaphore se puede usar para construir algunos grupos de objetos, grupos de recursos, etc., como grupos de conexión de bases de datos. También podemos crear semáforo con un recuento de 1, utilizándolo como un mecanismo similar a las cerraduras de Mutex. Esto también se llama semáforo binario, lo que indica dos estados mutex.
2. CountdownLatch
Esta clase se proporcionará después de JDK 1.5.
La clase CountdownLatch puede hacer que un hilo espere a que otros hilos completen su trabajo respectivo antes de ejecutar. Por ejemplo, el hilo principal de la aplicación desea ejecutar después del hilo responsable de iniciar el servicio Framework ha iniciado todos los servicios de Marco.
CountdownLatch se implementa a través de un contador, y el valor inicial del contador es el número de hilos. Cada vez que un hilo completa su propia tarea, el valor del contador se disminuye en 1. Cuando el valor del contador alcanza 0, significa que todos los hilos han completado la tarea, y luego los hilos que esperan en el bloqueo pueden reanudar la ejecución de la tarea.
Como se muestra en la figura a continuación:
Las dos clases anteriores se pueden usar en combinación para lograr el efecto de simular una alta concurrencia. El siguiente código se usa para dar un ejemplo:
módulos de paquete; import java.util.concurrent.countdownlatch; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.semaphore; public class CountExample {// Total de solicitudes Total de solicitudes Pública Pública intiental estática) = 5000; // número de hilos ejecutados simultáneamente al mismo tiempo público static int threadtotal = 200; Public static int count = 0; public static void main (string [] args) lanza la excepción {EjecutorService EjecutorService = Ejecutors.NewCachedThreadPool (); // semiconductor, utilizado para controlar el número de hilos concurrentes aquí semáforo final semáforo = nuevo semáforo (Threadtotal); // bloqueo, que puede realizar la disminución del contador final CountDownLatch CountdownLatch = new CountdownLatch (ClientTotal); for (int i = 0; i <clientToTal; i ++) {ExecessorService.ExeCute (() -> {try {// Ejecute este método para obtener el permiso de ejecución. Cuando el número total de licencias insonorizadas no exceda 200, // Permitir, en lo contrario, el hilo bloquea y espera hasta que se obtenga la licencia. } Catch (excepción e) {//log.error("exception ", e); } CountDownLatch.Await (); // Bloques de hilo, y el bloque no se libera hasta que el valor de bloqueo es 0. Continuar ejecutando ExecutorService.shutdown (); log.info ("Count: {}", Count); } private static void add () {count ++; }}Como se muestra en el método anterior, se simulan 5000 solicitudes, y 200 operaciones concurrentes son hasta 200 operaciones concurrentes al mismo tiempo. Observe los resultados finales y descubra que los resultados son diferentes para cada vez y son inconsistentes con las expectativas. El resultado es el siguiente:
22: 18: 26.449 [Main] módulos de información. COUNTEXample - Conteo: 4997
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. COUNTEXAMPLE - Conteo: 4995
22: 18: 26.449 [principal] módulos de información.
Conclusión final: el método Agregar no es seguro
Luego, cómo garantizar la seguridad del subproceso del método Agregar, modifique el método Agregar de la siguiente manera:
Private static void add () {count.incrementandget ();}Los resultados de la ejecución son los siguientes:
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
22: 18: 26.449 [Main] módulos de información. Entrexample - Conte: 5000
Conclusión final: el método ADD modificado Safe de hilo
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.