Serie de simultaneidad JUC (2): explicación detallada del uso de Condición en lugar de esperar y notificar [para lograr una activación de notificación precisa]

No es difícil ejecutar un programa; ¡lo difícil es qué tan lejos puede ejecutarse el programa! —— una semilla feroz

Inserte la descripción de la imagen aquí
Serie de concurrencia JUC

Primero familiarizado con la serie de concurrencia JUC (1): ¿qué? Escuché que confundes concurrencia y paralelismo

1. ¿Qué es la condición?

La condición se actualizó en jdk1.5, que se puede usar para reemplazar la espera y notificación original para lograr la cooperación entre subprocesos, porque los métodos de espera y señal de condición son más seguros y eficientes.

Puede ver la serie anterior de múltiples subprocesos en profundidad. Utilizamos el método de monitorización y el método de semáforo para resolver el problema de productores y consumidores mediante esperar y notificar .

Multi-threading en profundidad 15: el método de gestión para resolver el problema de productores y consumidores

Dieciséis subprocesos múltiples en profundidad: forma de semáforo para resolver el problema de productores y consumidores

2. Código de tipo de mano para lograr la condición para lograr una activación de notificación precisa

Hay un escenario en el que queremos que se ejecute un resultado de salida en el orden de ABC, luego usamos la Condición protagonista de hoy para lograrlo.

2.1 La condición no se usa

Antes de implementar la condición para notificar con precisión la activación, primero observe el segmento de código que no usa la condición para generar el resultado. (Comparar el aprendizaje es más intuitivo)

public class demo{
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testA();
           }
       },"一颗剽悍的种子A").start();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testB();
           }
       },"一颗剽悍的种子B").start();
       new Thread(()->{
    
    
           for (int i = 0; i < 5; i++) {
    
    
               data.testC();
           }
       },"一颗剽悍的种子C").start();
    }
}
class Data{
    
    
    public void testA(){
    
    
        System.out.println(Thread.currentThread().getName() + "A");
    }
    public void testB(){
    
    
        System.out.println(Thread.currentThread().getName() + "B");
    }
    public void testC(){
    
    
        System.out.println(Thread.currentThread().getName() + "C");
    }
}

resultado de la operación

Puede ver que el orden está desordenado, no en el orden de ejecución que queremos.

Inserte la descripción de la imagen aquí

2.2 Condición de uso para lograr una activación de notificación precisa

Synchronized es una cerradura exclusiva, el proceso de bloqueo y desbloqueo se realiza automáticamente, lo que es fácil de operar, pero no lo suficientemente flexible. ReentrantLock también es una cerradura exclusiva, pero el proceso de bloqueo y desbloqueo debe realizarse manualmente, lo cual no es fácil de operar, pero sí muy flexible.

Clave

Bloqueo manual -> Juicio -> Ejecución -> Notificación -> Bloqueo manual

    public void testA(){
    
    
        lock.lock();
        try {
    
    
        while (num != 1){
    
    
                conditionA.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "A");
            num++;
            conditionB.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }

Todos los códigos

public class demo{
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testA();
           }
       },"一颗剽悍的种子A").start();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testB();
           }
       },"一颗剽悍的种子B").start();
       new Thread(()->{
    
    
           for (Integer i = 0; i < 5; i++) {
    
    
               data.testC();
           }
       },"一颗剽悍的种子C").start();
    }
}
class Data{
    
    
    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private Condition conditionC = lock.newCondition();
    private Integer num = 1;    //1 = A  2 = B 3 = C

    public void testA(){
    
    
        lock.lock();
        try {
    
    
        while (num != 1){
    
    
                conditionA.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "A");
            num++;
            conditionB.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
    public void testB(){
    
    
        lock.lock();
        try {
    
    
            while (num != 2){
    
    
                conditionB.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "B");
            num++;
            conditionC.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
    public void testC(){
    
    
        lock.lock();
        try {
    
    
            while (num != 3){
    
    
                conditionC.await(); //等待
            }
            System.out.println(Thread.currentThread().getName() + "C");
            num = 1;
            conditionA.signal();    //通知
        }catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            lock.unlock();
        }
    }
}

resultado de la operación
Inserte la descripción de la imagen aquí

3. Evite los despertares falsos

Si ha visto la serie anterior de múltiples subprocesos en profundidad o el código anterior, si presta atención, encontrará que usamos el juicio while más que si en el juicio , porque si puede haber falsas activaciones.

Entonces, ¿qué es para prevenir despertares falsos?

El llamado falso despertar significa que aunque el hilo puede despertarse, no será notificado, interrumpido o agotado.

Cuatro, finalmente

Al final, para una mejor experiencia de lectura, pongo todo lo que quiero decir a continuación, jeje.

Soy semilla de decisiones basadas en mi voluntad, en serio compartir lo que escribí en el blog ha sido el mismo credo.
Si puedes leer esta entrada del blog, significa que todavía estamos muy destinados; espero que te pueda traer algo de ayuda, la creación no es fácil,
quita el conocimiento de mi artículo, tus tres seguidos dejan, me gusta, comenta, sigue , Es mi mayor motivación.

Supongo que te gusta

Origin blog.csdn.net/A_hxy/article/details/108665139
Recomendado
Clasificación