Hilo / proceso de comunicación

Comunicación entre procesos.

  1. Tubería (tubería): la tubería es un método de comunicación semidúplex, los datos solo pueden fluir en una dirección y solo pueden usarse entre procesos con relación sanguínea. La relación de sangre del proceso generalmente se refiere a la relación de proceso padre-hijo
  2. Canalización con nombre: la canalización con nombre también es un método de comunicación semidúplex, pero permite la comunicación de procesos no relacionados
  3. Semáforo (semáforo): un semáforo es un contador que se puede utilizar para controlar el acceso de múltiples procesos a recursos compartidos. Por lo general, se usa como un mecanismo de bloqueo para evitar que un proceso acceda a un recurso compartido mientras que otros procesos también acceden al recurso. Por lo tanto, se utiliza principalmente como método de sincronización entre procesos y entre diferentes hilos en el mismo proceso.
  4. Cola de mensajes (cola de mensajes): una cola de mensajes es una lista vinculada de mensajes, almacenada en el núcleo e identificada por un identificador de cola de mensajes. La cola de mensajes supera las deficiencias de menos información de transmisión de señal, la tubería solo puede transportar flujos de bytes sin formato y el tamaño de la memoria intermedia es limitado.
  5. Señal (señal): la señal es un método de comunicación más complejo, utilizado para notificar al proceso de recepción que se ha producido un evento.
  6. Memoria compartida (memoria compartida): la memoria compartida es una pieza de memoria a la que pueden acceder otros procesos. Esta memoria compartida se crea mediante un proceso, pero varios procesos pueden acceder a ella. La memoria compartida es el método IPC más rápido. Está dirigido a El método de comunicación entre otros procesos está especialmente diseñado para ejecutarse de manera ineficiente. A menudo se usa junto con otros mecanismos de comunicación, como los semáforos, para lograr la sincronización y la comunicación entre procesos.
  7. Socket (socket): el socket también es un mecanismo de comunicación entre procesos, a diferencia de otros mecanismos de comunicación, se puede utilizar para una comunicación diferente y entre procesos.
  8. Asignación de memoria: la asignación de memoria permite la comunicación entre múltiples procesos. Cada proceso que utiliza este mecanismo lo implementa asignando un archivo compartido a su propio espacio de dirección de proceso

Mecanismo de comunicación entre hilos

  Hay dos modelos de comunicación entre hilos: memoria compartida y paso de mensajes .

题目:有两个线程ABA线程向一个集合里面依次添加元素
"abc"字符串,一共添加十次,当添加到第五次的时候,
希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作。

Método 1: use la palabra clave volátil

  Es la idea de usar la memoria compartida para realizar una comunicación mutua entre hilos basándose en la palabra clave volátil, es decir, varios hilos escuchan una variable al mismo tiempo. Cuando esta variable cambia, el hilo puede percibir y ejecutar el negocio correspondiente. Esta es también la forma más sencilla de lograr

public class TestSync {
    // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
    static volatile boolean notice = false;
    public static void main(String[] args) {
        List<String>  list = new ArrayList<>();
        // 实现线程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    notice = true;
            }
        });
        // 实现线程B
        Thread threadB = new Thread(() -> {
            while (true) {
                if (notice) {
                    System.out.println("线程B收到通知,开始执行自己的业务...");
                    break;
                }
            }
        });
        // 需要先启动线程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再启动线程A
        threadA.start();
    }
}

Método 2: utilice los métodos wait () y notify () de la clase Object

  La clase Object proporciona métodos para la comunicación entre subprocesos: wait (), notify (), notifyaAll (), son la base de la comunicación multiproceso y la idea de esta implementación es, naturalmente, la comunicación entre subprocesos. Nota: esperar y notificar debe usarse con sincronizado, el método de espera libera el bloqueo, el método de notificación no libera el bloqueo

public class TestSync {
    public static void main(String[] args) {
        // 定义一个锁对象
        Object lock = new Object();
        List<String>  list = new ArrayList<>();
        // 实现线程A
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        lock.notify();// 唤醒B线程
                }
            }
        });
        // 实现线程B
        Thread threadB = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    if (list.size() != 5) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("线程B收到通知,开始执行自己的业务...");
                }
            }
        });
        // 需要先启动线程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再启动线程A
        threadA.start();
    }
}

Después de que el subproceso A emita la notificación de activación de notify (), el subproceso B solo comienza a ejecutarse después de ejecutar el negocio de su propio subproceso. Esto también muestra que el método notify () no libera el bloqueo, mientras que el método wait () libera el bloqueo.

Método 3: utilizar la clase de herramienta JUC CountDownLatch

  Después de jdk1.5, hay muchas clases de herramientas relacionadas con la programación concurrente en el paquete java.util.concurrent. CountDownLatch se basa en el marco AQS, que es equivalente a mantener un estado variable compartido entre subprocesos

public class TestSync {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<String>  list = new ArrayList<>();
        // 实现线程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    countDownLatch.countDown();
            }
        });
        // 实现线程B
        Thread threadB = new Thread(() -> {
            while (true) {
                if (list.size() != 5) {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("线程B收到通知,开始执行自己的业务...");
                break;
            }
        });
        // 需要先启动线程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再启动线程A
        threadA.start();
    }
}

Método 4: usar ReentrantLock con condición

public class TestSync {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        List<String> list = new ArrayList<>();
        // 实现线程A
        Thread threadA = new Thread(() -> {
            lock.lock();
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    condition.signal();

            }
            lock.unlock();
        });
        // 实现线程B
        Thread threadB = new Thread(() -> {
            lock.lock();
            if (list.size() != 5) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程B收到通知,开始执行自己的业务...");
            lock.unlock();
        });
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadA.start();
    }
}

El código de escritura no solo es complejo de esta manera, sino que el subproceso B no se puede ejecutar inmediatamente después de que A lo despierta porque no adquiere el bloqueo, es decir, A no libera el bloqueo después de la operación de activación. Este método es el mismo que wait () y notify () de Object.

Método 5: soporte básico de bloqueo para lograr el bloqueo y la activación entre subprocesos

  LockSupport es una herramienta muy flexible para bloquear y despertar entre hilos. Úselo sin tener en cuenta si esperar a que el hilo se ejecute primero o activar el hilo primero, pero necesita saber el nombre del hilo.

public class TestSync {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        // 实现线程B
        final Thread threadB = new Thread(() -> {
            if (list.size() != 5) {
                LockSupport.park();
            }
            System.out.println("线程B收到通知,开始执行自己的业务...");
        });
        // 实现线程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    LockSupport.unpark(threadB);
            }
        });
        threadA.start();
        threadB.start();
    }
}

———————————————————————————————————————

La diferencia entre proceso e hilo

  Un proceso es una unidad independiente para la asignación y programación de recursos por parte del sistema.
  Un subproceso es una entidad de un proceso y es la unidad básica de programación y despacho de la CPU. Es una unidad básica que es más pequeña que un proceso y puede ejecutarse independientemente. Un hilo tiene su propia pila y variables locales. Un hilo tiene su propio espacio de pila (como un contador de programa, un conjunto de registros y una pila), pero puede compartir todos los recursos que posee el proceso con otros hilos que pertenecen al mismo proceso.

Diferencia
  La principal diferencia entre procesos y subprocesos es que son formas diferentes de gestión de recursos del sistema operativo. Los procesos tienen espacios de direcciones independientes. Después de que un proceso falla, no afectará a otros procesos en modo protegido, y los subprocesos son solo rutas de ejecución diferentes en un proceso. Los subprocesos tienen su propia pila y variables locales, y tienen secuencias de ejecución independientes, pero no hay espacio de direcciones separado entre los subprocesos. La muerte de un subproceso es igual a la muerte de todo el proceso, por lo que los programas multiproceso son más robustos que los programas multiproceso, pero Cuando se cambia el proceso, consume más recursos y la eficiencia es peor. Sin embargo, para operaciones simultáneas que requieren la ejecución simultánea y el intercambio de ciertas variables, solo se pueden usar hilos, no procesos.

162 artículos originales publicados · elogiados 58 · 90,000 visitas

Supongo que te gusta

Origin blog.csdn.net/ThreeAspects/article/details/105539033
Recomendado
Clasificación