Pregunta de la entrevista: ¿Conoce ReentrantLock? Responder ideas

Respuesta: El primer paso: no lo he usado normalmente, sincronizado no puede satisfacer todas las ocasiones. ReentrantLock se implementa mediante la clase java, mientras que la sincronización se implementa mediante la capa jvm. ReentrantLock es más flexible pero también peligroso. Puede interrumpir el hilo que solicita el bloqueo o puede permitir que el hilo espere indefinidamente.

Paso 2: Luego hablo brevemente sobre su principio.
(1) Su principio se basa en AQS (AbstractQueuedSynchronizer). Cuando varios subprocesos toman el bloqueo, si el agarre falla, entrarán en la cola de bloqueo. Espere a que se despierte e intente bloquear de nuevo.
(2) Las subclases de AQS incluyen FairSync de bloqueo justo y NofairSync de bloqueo injusto. La estructura sin parámetros de ReentrantLock se establece de forma predeterminada en bloqueo injusto, y el parámetro de la estructura parametrizada es verdadero si se establece en bloqueo justo.
(3) Fair lock: ReentrantLock llama al método de bloqueo y finalmente llama a la función tryAcquire de la clase Sync para obtener recursos. El hilo actual solo puede obtener recursos cuando la cola está vacía o el primer nodo de la cola, de lo contrario se agregará a la cola de bloqueo.
(4) Bloqueo injusto: también llama a tryAcquire de sync, la diferencia es que tryAcquire también llama a nofairTryAcquire.
(5) La diferencia entre un bloqueo justo y un bloqueo injusto: un bloqueo injusto tomará inmediatamente el bloqueo CAS cuando se llame al bloqueo de NonfairSync. Si no se obtiene, ingresará al método tryAcquire como un bloqueo justo para intentar agarre el candado Si se encuentra que el candado se libera (Estado == 0), los candados injustos inmediatamente CAS toma el candado, sin importar si hay hilos esperando en la cola de bloqueo. La cerradura de la feria esperará en la fila.

ReentrantLock:

public ReentrantLock() {
	sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

Cerradura justa: FairSync  

 static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
 
        final void lock() {
            acquire(1);
        }
       //尝试直接获取锁,返回值是boolean,代表是否获取到锁
       //返回true:
        //1.没有线程在等待锁;
        //2.重入锁,线程本来就持有锁,也就可以理所当然可以直接获取
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //关键点
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //判断是有锁的线程是否为当前线程。
            //可重入就在这里体现的,同一个线程多次调用lock方法
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

 Bloqueo injusto: NonfairSync 

static final class NonfairSync extends Sync {
     private static final long serialVersionUID = 7316153563782823691L;
 
     /**
      * Performs lock.  Try immediate barge, backing up to normal
      * acquire on failure.
      */
     final void lock() {
         //不管AQS队列有没有等待的线程,直接开始抢
         if (compareAndSetState(0, 1))
             setExclusiveOwnerThread(Thread.currentThread());
         else
            acquire(1);
     }
 
     protected final boolean tryAcquire(int acquires) {
         return nonfairTryAcquire(acquires);
     }
 }

Respuestas de pacientes con deterioro de la memoria (yo soy):

El primer paso: no lo he usado normalmente, el sincronizado se usa más, pero no cumple con todos los requisitos. ReentrantLock es más flexible, puede interrumpir operaciones como el hilo que solicita el bloqueo.

Paso 2: Hablando brevemente, hay dos implementaciones internas, una es un bloqueo justo, la otra es un bloqueo injusto y el predeterminado es un bloqueo injusto Tiene un método tryAcquire para intentar adquirir el bloqueo.

      Luego, la cerradura injusta intentará agarrar la cerradura dos veces, la primera vez que no pueda agarrarla, esperará a que se libere la cerradura y el CAS agarrará la cerradura tan pronto como se suelte, y si la agarra falla, entra en la cola de bloqueo y espera el despertar.

Respuestas a las ideas: 1. Explique que ReentrantLock es una clase de Java, y puede hacer más cosas en comparación con sincronizada; 2. Hablemos del bloqueo justo interno y del bloqueo injusto, centrándonos en el hecho de que hay dos bloqueos "dominantes" para el bloqueo injusto. Cerraduras.

 

¡Bienvenidos a intercambiar y aprender juntos!

 

 

Materiales de referencia: https://blog.csdn.net/zycxnanwang/article/details/105321401

https://blog.csdn.net/o9109003234/article/details/106066537

Supongo que te gusta

Origin blog.csdn.net/x18094/article/details/114608629
Recomendado
Clasificación