Breve análisis del principio sincronizado y el principio de realización del mecanismo de notificación de espera en el objeto Java

¿Cuál es el mecanismo de notificación en espera en la programación concurrente? En resumen, un hilo modifica el valor de un objeto y otro hilo percibe el cambio y luego realiza la operación correspondiente. En el blog anterior , el uso de LockSupport y Condition of Java JUC Concurrent Package Components , presentamos el mecanismo de notificación de espera implementado usando el sincronizador de cola. En este artículo, presentamos el mecanismo de notificación de espera de los objetos Java implementados usando sincronizado, y la espera / notificación relacionada Los métodos están disponibles para cualquier objeto Java, porque estos métodos se definen en la superclase java.lang.Object de todos los objetos. Los métodos y descripciones se muestran en la siguiente tabla:

Nombre del método

descripción

Espere()

El hilo que llama a este método entra en estado de ESPERA y solo regresará cuando otro hilo lo notifique o se interrumpa. Tenga en cuenta que el bloqueo del objeto se liberará después de llamar al método de espera

espera (largo)

Espere un momento, si no hay notificación, se agotará el tiempo de espera y volverá. El parámetro es milisegundos

esperar (largo, int)

Control más detallado del período de tiempo de espera, hasta nanosegundos

notificar()

Notifique a un hilo que espera que el objeto regrese del método de espera, y la premisa de la devolución es que el hilo ha adquirido el bloqueo del objeto

notificar a todos ()

Notifique a todos los hilos que esperan el objeto

El método anterior: un subproceso A llama al método wait () del objeto O para entrar en el estado de espera, y otro subproceso B llama al método notificar () o notificar a todos () del objeto O, y el subproceso A recibe la notificación del esperar () del objeto O ) El método regresa y luego realiza las operaciones subsiguientes. Este es el mecanismo de notificación de espera de los objetos Java. Estos métodos deben usarse con sincronizado. Primero, primero presentamos el principio de implementación de sincronizado. La palabra clave sincronizada puede modificar el método o usarlo en forma de bloque sincronizado. Principalmente asegura que varios subprocesos solo puedan estar en un método o bloque de sincronización al mismo tiempo. Asegura la visibilidad y exclusividad del acceso de subprocesos a las variables.

En la introducción anterior al uso de sincronizado, se ha introducido que cualquier objeto tiene su propio monitor. Cuando este objeto es llamado por el bloque de sincronización o el método de sincronización de este objeto, el hilo que ejecuta el método debe obtener primero el monitor del objeto antes de que pueda entrar en sincronización. Bloque o método de sincronización, pero no obtuvo el monitor (ejecutar el método) el hilo será bloqueado a la entrada del bloque de sincronización y método de sincronización, ingrese al estado BLOQUEADO, la siguiente figura describe el objeto, monitor de objeto, cola de sincronización y La relación entre los hilos de ejecución:

 El acceso de cualquier hilo a un objeto (el objeto está protegido por sincronización) debe obtener primero un monitor de objeto. Si la adquisición falla, el subproceso ingresa a la cola de sincronización y el estado del subproceso se vuelve BLOQUEADO. Cuando el predecesor de acceder al Objeto (el hilo que adquirió el bloqueo) libera el bloqueo, la operación de liberación despierta el hilo bloqueado en la cola de sincronización para que vuelva a intentar la adquisición del monitor. Aquí ya no se está introduciendo el uso de sincronizados, puede referirse a la seguridad del hilo del blog y el uso de sincronización y bloqueo de actualización .

Anteriormente presentamos la implementación interna de sincronizados. A continuación presentamos la implementación del mecanismo de notificación en espera para objetos Java. En comparación con la implementación sincronizada, el mecanismo de notificación en espera se implementa sobre la base de la implementación sincronizada y el proceso es más complicado. Primero escribamos un ejemplo de esperar notificación, el código es el siguiente:

public class WaitNotify {
    static boolean flag = true;
    static Object lock = new Object();
    public static void main(String[] args) throws Exception {
	//等待线程
	Thread waitThread = new Thread(new Wait(), "WaitThread");
	waitThread.start();
	TimeUnit.SECONDS.sleep(1);
	//通知线程
	Thread notifyThread = new Thread(new Notify(), "NotifyThread");
	notifyThread.start();
    }

    static class Wait implements Runnable {
        public void run() {
	    // 加锁,拥有lock的Monitor
	    synchronized (lock) { 
		// 当条件不满足时,继续wait,同时释放了lock的锁
		while (flag) {
		    try {
		        System.out.println("WAITING 线程启动并且执行");
		        //调用wait方法,线程进入WAITING状态
			lock.wait();
		    } catch (InterruptedException e) {
					}
		} // 条件满足时,完成工作
            }
            System.out.println("收到 notify通知,获取对象监视器,继续执行");
        }
    }

    static class Notify implements Runnable {
	public void run() {
	    // 加锁,拥有lock的Monitor
	    synchronized (lock) { 
            // 获取lock的锁,然后进行通知,通知时不会释放lock的锁, 
	    System.out.println("通知线程启动");
	    //通知其他处理WAITING状态的线程
	    lock.notifyAll();
	    flag = false;
	    }
	}
    }
}

En el ejemplo anterior, podemos ver que el mecanismo de espera / notificación de los objetos Java se basa en el mecanismo de sincronización, cuyo propósito es asegurar que el hilo en espera pueda percibir la modificación de la variable realizada por el hilo de notificación cuando regresa del método wait (). En el ejemplo anterior, WaitThread primero adquiere el bloqueo del objeto y luego llama al método wait () del objeto, abandonando así el bloqueo y entrando en WaitQueue del objeto, entrando en el estado de espera. Debido a que WaitThread libera el bloqueo del objeto, NotifyThread posteriormente adquiere el bloqueo del objeto y llama al método notificar () del objeto para mover WaitThread de WaitQueue a SynchronizedQueue. En este momento, el estado de WaitThread se bloquea. Después de que NotifyThread libera el bloqueo, WaitThread vuelve a adquirir el bloqueo y regresa del método wait () para continuar con la ejecución. El siguiente es su diagrama de flujo de transición de estado:

Supongo que te gusta

Origin blog.csdn.net/wk19920726/article/details/108710059
Recomendado
Clasificación