Para aprender programación de concurrencia Java, tenemos que aprender sobre el paquete java.util.concurrent. Hay muchas clases de herramientas de concurrencia que a menudo usamos bajo este paquete, como: ReentrantLock, CountdownLatch, CyclicBarrier, Semafore, etc. La implementación subyacente de estas clases depende de la clase de Synchronizer abstractqueededynchronizer, que muestra la importancia de esta clase. Entonces, en la serie de concurrencia Java, primero analicé la clase de Synchronizer Abstractqueed. Dado que esta clase es más importante y el código es relativamente largo, para analizarla lo más a fondo posible, decidí usar cuatro artículos para dar una introducción relativamente completa a esta clase. Este artículo es una introducción resumida para dar a los lectores una comprensión preliminar de esta categoría. En aras de la simplicidad de la narración, algunos lugares utilizarán AQS para representar esta clase en el futuro.
1. ¿Para qué sirve la clase de Synchronizer de Abstractqueed?
Creo que muchos lectores han usado Reentrantlock, pero no conocen la existencia de StraceDeedSynchronizer. De hecho, Reentrantlock implementa una sincronización de clase interna, que hereda el sistema de resumen de la cosecha. Todas las implementaciones de mecanismo de bloqueo se basan en clases de sincronización internas. También se puede decir que la implementación de ReentrantLock depende de la clase de SynChronizer abstractqueed. Del mismo modo, CountdownLatch, CyclicBarrier y Semaphore Classes también utilizan el mismo método para implementar su propio control de los bloqueos. Se puede ver que AbstractqueedSynchronizer es la piedra angular de estas clases. Entonces, ¿qué se implementa exactamente dentro de AQS para que todas estas clases dependan de ello? Se puede decir que AQS proporciona infraestructura para estas clases, es decir, proporciona un bloqueo de contraseña. Después de que estas clases tienen un bloqueo de contraseña, pueden establecer la contraseña del bloqueo de contraseña por sí mismos. Además, AQS también proporciona un área de cola y un instructor de hilo. Sabemos que los hilos son como un bárbaro primitivo. No saben cómo ser educados. Solo se apresurarán, por lo que debe enseñarlo paso a paso, decirle cuándo necesita hacer cola, dónde hacer cola, qué hacer antes de hacer cola y qué hacer después de hacer cola. AQS para usted completan todos estos trabajos educativos. Los hilos educados de él se han vuelto muy civilizados y educados, y ya no son bárbaros primitivos. Entonces, en el futuro, solo necesitamos lidiar con estos hilos civilizados. ¡Nunca tenga demasiado contacto con los hilos originales!
2. ¿Por qué abstractQueueynchronizer proporciona un bloqueo de contraseña?
// El nodo principal del cabezal de nodo volátil transitorio privado de la cola privada; // El nodo de cola de la cola de nodo volátil privado de la cola privada; // el estado intivido intencion intencion; // get sincronización estado protegido final int getState () {state de retorno;} // Establecer el estado final de sincronización de sincronización Final setstate (int NewState) {state = newState;} // set State de sincronización protegida final void setstate (int NewState) {state = newState;} // set State de sincronización Boolean de bobina {return unsafe.compareandswapint (this, stateOffset, espere, actualización);}El código anterior enumera todas las variables de miembros de AQS. Puede ver que solo hay tres variables miembros de AQS, a saber, la referencia del nodo del cabezal de la cola de sincronización, la referencia del nodo de cola de cola de sincronización y el estado de sincronización. Tenga en cuenta que las tres variables miembros se modifican con la palabra clave volátil, que asegura que múltiples subprocesos lo modifiquen es visible de memoria. El núcleo de toda la clase es este estado de sincronización. Puede ver que el estado de sincronización es en realidad una variable de tipo INT. Puede considerar este estado de sincronización como un bloqueo de contraseña, y también es un bloqueo de contraseña bloqueado de la habitación. El valor específico del estado es equivalente a la contraseña que controla la apertura y el cierre del bloqueo de contraseña. Por supuesto, la contraseña de este bloqueo está determinada por cada subclase. Por ejemplo, en reentrantlock, el estado es igual a 0 significa que el bloqueo está abierto, el estado mayor de 0 significa que el bloqueo está bloqueado y en semáforo, el estado mayor de 0 significa que el bloqueo está abierto y el estado es igual a 0 significa que el bloqueo está bloqueado.
3. ¿Cómo se implementa el área de la cola de AbstractqueedSynchronizer?
En realidad, hay dos áreas de cola dentro de StracequeedSynchronizer, una es una cola sincrónica y la otra es una cola condicional. Como se puede ver en la figura anterior, solo hay una cola de sincronización, mientras que puede haber múltiples colas de condición. Los nodos de la cola sincrónica contienen referencias a los nodos delanteros y traseros respectivamente, mientras que los nodos de la cola condicional solo tienen una referencia al nodo sucesor. En la figura, T representa un hilo. Cada nodo contiene un hilo. Después de que el hilo no logra adquirir el bloqueo, primero ingresa a la cola de sincronización para hacer cola. Si desea ingresar a la cola condicional, el hilo debe sostener el bloqueo. A continuación, echemos un vistazo a la estructura de cada nodo en la cola.
// Los nodos de la cola sincrónica son el nodo de clase final estática {nodo final estático compartido = nuevo nodo (); // El hilo actual contiene el bloqueo en modo compartido nodo final estático exclusive = null; // El hilo actual contiene el bloqueo en modo exclusivo estático final int cancelado = 1; // El nodo actual ha cancelado el bloqueo final de la señal int static final = -1; // Los hilos del nodo sucesor deben ejecutar la condición final estática int -int = -2; // El nodo actual está en cola en la cola condicional estática final int propagate = -3; // El nodo posterior puede adquirir directamente el bloqueo de Lock Volátil int WaitStatus; // denota el estado de espera del nodo del nodo actual anterior previo; // denota el nodo directo en el nodo volátil de la cola de sincronización siguiente; // denota el nodo sucesor en el hilo volátil de la cola de sincronización; // El hilo sostenido por el nodo actual se refiere al nodo NextWaiter; // denota el nodo sucesor en la cola condicional // es el estado del nodo actual en el modo compartido boolean isshared () {return nextwaiter == compartido; } // Devuelve el nodo avanzado del nodo del nodo actual predecesor () lanza nullPointerException {nodo p = prev; if (p == null) {lanzar new nullPointerException (); } else {return p; }} // constructor 1 nodo () {} // Constructor 2, este constructor se usa por nodo predeterminado (hilo de subproceso, modo de nodo) {// Tenga en cuenta que el modo de retención se asigna a NextWaIter this.nextwaitrer = modo; this.thread = hilo; } // Constructor 3, solo nodo (hilo de hilo, int waitStatus) se usa en la cola de condición {this.waitStatus = waitStatus; this.thread = hilo; }}El nodo representa un nodo en la cola de sincronización y la cola condicional. Es una clase interna de syncronizer de abstracción. El nodo tiene muchos atributos, como el modo de retención, el estado de espera, la pre-secuencia y el sucesor en las colas sincrónicas, y las referencias sucesoras en las colas condicionales, etc. La cola de sincronización y la cola de condición pueden considerarse como un área de cola, cada nodo se considera un asiento en el área de la cola, y el hilo se considera como un invitado de cola. Cuando los invitados vienen por primera vez, tocan la puerta para ver si se abre la cerradura. Si no se abre la cerradura, irán al área de la cola para recolectar una matrícula, declarar de qué manera quieren sostener la cerradura y finalmente cola al final de la cola.
4 ¿Cómo entender el modo exclusivo y el modo de intercambio?
Como se mencionó anteriormente, cada invitado recibirá una matrícula antes de hacer cola y declarar que quiere poseer la cerradura. La forma de poseer el bloqueo se divide en modo exclusivo y modo de intercambio. Entonces, ¿cómo entiendes el modo exclusivo y el modo de intercambio? Realmente no puedo encontrar ninguna buena analogía. Puedes pensar en un baño público. Las personas con modo exclusivo son más dominantes. O no entro. Cuando entro, no permito que otros entren. Ocupo todo el baño solo. Las personas en el modo de intercambio no son tan particulares. Cuando descubren que el inodoro ya es utilizable, no cuenta si llega por sí mismo. También tienen que preguntarle con entusiasmo a las personas si les importa usarlo juntos. Si a las personas detrás no les importa usarlo juntos, no hay necesidad de hacer cola. Todos irán juntos. Por supuesto, si las personas detrás de ellos les importa, tienen que permanecer en la cola y continuar haciendo cola.
5 ¿Cómo entender el estado de espera de un nodo?
También vemos que cada nodo tiene un estado de espera, que se divide en cuatro estados: cancelado, señal, condición y propagación. Este estado de espera puede considerarse como un letrero que cuelga al lado del asiento, identificando el estado de espera de la persona en el asiento actual. El estado de esta marca no solo puede ser modificado por usted mismo, sino que otros también pueden modificarlo. Por ejemplo, cuando este hilo ya ha planeado rendirse durante la cola, establecerá el letrero en su asiento para cancelarse, para que otros puedan eliminarlo de la cola si lo ven. Otra situación es que cuando el hilo está a punto de quedarse dormido en el asiento, tiene miedo de que se quede demasiado dormido, por lo que cambiará el letrero en la posición delantera para señalar, porque todos volverán a sus asientos antes de dejar la cola para echar un vistazo. Si ve que el estado en la señal es señal, despertará a la siguiente persona. Solo asegurando que la marca en la posición delantera sea señal, el hilo actual dormirá pacíficamente. El estado de la condición indica que el hilo está en cola en la cola condicional. El estado de propagación recuerda a los hilos posteriores para adquirir el bloqueo directamente. Este estado solo se usa en el modo compartido y se discutirá más adelante cuando se habla del modo compartido por separado.
6. ¿Qué operaciones se realizarán cuando un nodo ingrese a la cola de sincronización?
// operación de enqueue de nodo, regrese al nodo privado anterior enq (nodo del nodo final) {for (;;) {// Obtenga la referencia al nodo de cola del nodo de cola de sincronización t = cola; // Si el nodo de la cola está vacío, significa que la cola de sincronización no se ha inicializado si (t == null) {// inicializa la cola de sincronización if (compareAndsethead (new node ())) {tail = head; }} else {// 1. Apunte al nodo del nodo de cola actual.prev = t; // 2. Establezca el nodo actual en el nodo de cola if (compareSettail (t, nodo)) {// 3. Apunte al sucesor del nodo de cola antiguo al nuevo nodo de cola t.next = nodo; // La única salida del bucle for devuelve t; }}}}Tenga en cuenta que la operación de Enqueue usa un bucle muerto. Solo cuando el nodo se agregue con éxito a la cola de la cola de sincronización, se devolverá. El resultado es el nodo de cola original de la cola de sincronización. La siguiente figura muestra todo el proceso de operación.
Los lectores deben prestar atención al orden de agregar nodos de cola, que se dividen en tres pasos: apuntando a nodos de cola, CAS cambia los nodos de cola y apuntando a los sucesores del nodo de cola antiguo al nodo actual. En un entorno concurrente, no se pueden garantizar que estos tres pasos se completen. Por lo tanto, en el funcionamiento de la limpieza de todos los nodos cancelados en la cola de sincronización, para encontrar nodos en un estado no cancelado, no se atraviesa de adelante hacia atrás, sino de espalda a delantera. Además, cuando cada nodo ingresa a la cola, su estado de espera es 0. Solo cuando el hilo del nodo posterior debe suspenderse el estado de espera del nodo anterior se cambiará a la señal.
Nota: Todo el análisis anterior se basa en JDK1.7, y habrá diferencias entre diferentes versiones, los lectores deben prestar atención.
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.