Traducción de documentos AbstractQueuedSynchronizer

   I. Panorama general 

        Proporcionar un marco para implementar bloqueos de bloqueo y sincronizadores relacionados (semáforos, eventos, etc.) que se basan en colas de espera primero en entrar, primero en salir (FIFO). Esta clase está destinada a proporcionar una base útil para la mayoría de los sincronizadores que se basan en un único valor atómico int para representar el estado. La subclase debe definir un método protegido para cambiar este estado y definir qué significa este estado para adquirir o liberar este objeto. En vista de estos, otros métodos de esta clase realizarán todos los mecanismos de cola y bloqueo. Las subclases pueden mantener otros campos de estado, pero solo para obtener sincronización y solo rastrear el uso de los métodos getState (), setState (int) y compareAndSetState (int, int) para manipular los valores int actualizados atómicamente.

       La subclase debe definirse como una clase auxiliar interna no pública que se utiliza para implementar las propiedades de sincronización de la clase en la que se encuentra. AbstractQueuedSynchronizer no implementa ninguna interfaz de sincronización. Por el contrario, define métodos como adquirirInterruptible, que se puede llamar adecuadamente a través de bloqueos específicos y sincronizadores relacionados para implementar sus métodos públicos.

        Esta clase admite uno de los modos exclusivos y compartidos predeterminados. Cuando la adquisición se realiza exclusivamente, las adquisiciones intentadas por otros subprocesos no tendrán éxito. El modo compartido adquirido por varios subprocesos puede (pero no necesariamente) tener éxito. Esta clase no comprende estas diferencias, pero en un sentido mecánico, cuando el modo compartido se adquiere con éxito, el siguiente hilo en espera (si existe) también debe determinar si también se puede adquirir. Los subprocesos que esperan en diferentes modos comparten la misma cola FIFO. Por lo general, la subclase de implementación solo admite uno de estos modos, pero ambos modos pueden desempeñar un papel en ReadWriteLock. Las subclases que solo admiten modos exclusivos o compartidos no necesitan definir métodos que admitan modos no utilizados.

       Esta clase define una clase ConditionObject anidada, que las subclases que admiten el modo exclusivo pueden utilizar como implementación de Condition. IsHeldExclusively informa si la sincronización está reservada exclusivamente en relación con el hilo actual. Utilice el valor getState actual para llamar al método release (int) para libérelo por completo Este objeto; si se le da un valor de estado guardado, el método de adquisición (int) finalmente puede restaurar este objeto al estado que adquirió previamente. De lo contrario, ningún otro método AbstractQueuedSynchronizer creará tal condición, por lo que si esta restricción no se puede cumplir, no la use. El comportamiento de AbstractQueuedSynchronizer.ConditionObject, por supuesto, depende de la semántica de su implementación de sincronizador.

       Esta clase proporciona métodos para verificar, detectar y monitorear colas internas, así como métodos similares para objetos de condición. . El AbstractQueuedSynchronizer para su mecanismo de sincronización se puede utilizar para exportar estos métodos a la clase según sea necesario.

      Este tipo de serialización solo almacena el estado básico de mantenimiento del entero atómico, por lo que el objeto deserializado tiene una cola de subprocesos vacía. Una subclase típica que requiere serialización definirá un método readObject que puede restaurarlo a un estado inicial conocido durante la deserialización.

Dos, uso

        Para usar esta clase como base de un sincronizador, debe redefinir los siguientes métodos de manera apropiada. Esto se hace usando los métodos getState (), setState (int) y / o compareAndSetState (int, int) para verificar y / o modificar el estado de sincronización logrado:

  1. tryAcquire
  2. tryRelease
  3. tryAcquireShared
  4. tryReleaseShared
  5. isHeldExclusively

       De forma predeterminada, cada uno de estos métodos generará UnsupportedOperationException. La implementación de estos métodos debe ser internamente segura para subprocesos y, por lo general, debe ser breve y sin bloqueo. La definición de estos métodos es la única forma admitida de utilizar esta clase. Todos los demás métodos se declaran finales porque no se pueden cambiar de forma independiente.

        También puede encontrar los métodos heredados de AbstractOwnableSynchronizer útiles para rastrear hilos que tienen sincronizadores exclusivos. Se le anima a usarlos, lo que habilitará herramientas de monitoreo y diagnóstico para ayudar a los usuarios a determinar qué subprocesos tienen bloqueos.

       Incluso si este tipo se basa en la cola FIFO interna, no ejecutará automáticamente la estrategia de adquisición FIFO. El núcleo de la sincronización exclusiva toma la siguiente forma: (El modo de compartir es similar, pero puede involucrar señales en cascada)

  Adquirir:

     // La adquisición falló
      mientras (! TryAcquire (arg)) {

         Si el hilo no se ha puesto en cola, agregarlo a la cola
         puede bloquear el hilo actual;
      }
 
  Liberar:
      if (tryRelease (arg))

          Desbloquear el primer hilo en cola

 

      Debido a que es necesario verificar el estado de adquisición del subproceso antes de unirse a la cola, el nuevo subproceso de adquisición puede insertarse antes que otros subprocesos que están bloqueados y en cola. Sin embargo, si es necesario, puede definir tryAcquire y / o tryAcquireShared para deshabilitar la inserción llamando internamente a uno o más métodos de verificación, proporcionando así una orden de adquisición FIFO justa. En particular, si hasQueuedPredecessors (un método diseñado específicamente para sincronizadores justos) devuelve verdadero, la mayoría de los sincronizadores justos pueden definir tryAcquire para que devuelva falso. Son posibles otros cambios.

       Para las estrategias de inserción predeterminadas (también conocidas como codiciosas, renuncia y evitación de convoyes), el rendimiento y la escalabilidad suelen ser los más altos. Aunque no hay garantía de que esto sea justo o imparcial, los subprocesos que se unen a la cola antes pueden competir por recursos nuevamente antes que los subprocesos que se unen a la cola más tarde, y cada subproceso que participa en la contienda se compara con el subproceso entrante. igualdad de oportunidades para el éxito. Además, aunque las adquisiciones no son "giros" en un sentido general, pueden realizar múltiples llamadas a tryAcquire utilizadas por otros cálculos antes del bloqueo. Si la sincronización exclusiva solo se mantiene brevemente, esto proporciona el mayor beneficio para los efectos, pero cuando este no es el caso, no supondrá una gran carga. Si necesita hacer esto, puede usar la verificación de "ruta rápida" para llamar al método de adquisición primero para expandir esta función. Si es posible que no necesite competir por el sincronizador, solo puede confirmar esto marcando hasContended () y / o hasQueuedThreads () por adelantado un poco.

      Al especializar el alcance de uso de su sincronizador, esta clase proporciona una base eficaz y escalable para la sincronización parcial. El sincronizador puede confiar en el estado de tipo int, adquirir y liberar parámetros y una cola de espera FIFO interna. Cuando estos no son suficientes, puede usar la clase atómica, su propia clase de cola personalizada y el soporte de bloqueo LockSupport para construir un sincronizador desde un nivel inferior.

Tres, muestra

       Esta es una clase de bloqueo no reentrante mutuamente excluyente. El valor 0 se usa para indicar el estado desbloqueado y el valor 1 se usa para indicar el estado bloqueado. Aunque los bloqueos no reentrantes no son estrictamente necesarios para registrar el hilo propietario actual, esta clase lo hará de todos modos para facilitar la supervisión del uso. También admite condiciones y divulga un método de detección.

class Mutex implementa Lock, java.io.Serializable { 
    
    / ** 
     * Clase auxiliar interna 
     * / 
    clase estática privada Sync extiende AbstractQueuedSynchronizer { 
        // Registra si el bloqueo se mantiene 
        @Override 
        protected boolean isHeldExclusively () { 
            return getState () == 1 ; 
        } 

        // Adquirir el bloqueo si el valor de estado es 0 
        @Override 
        public boolean tryAcquire (int adquiere) { 
            assert adquiere == 1; // De lo contrario, no se 
            usa if (compareAndSetState (0, 1)) { 
                setExclusiveOwnerThread (Thread.currentThread () ); 
                devuelve verdadero; 
            } 
            devuelve falso;
        } 
         * /

        // 释放 锁 通过 设置 estado0 @Override 
        protected boolean tryRelease (int releases) { 
            assert releases == 1; // De lo contrario, no se 
            usa if (getState () == 0) { 
                throw new IllegalMonitorStateException (); 
            } 
            setExclusiveOwnerThread (nulo); 
            setState (0); 
            devuelve verdadero; 
        } 

        / ** 
         * Proporciona una Condición 
         * / 
        Condición newCondition () { 
            return new ConditionObject (); 
        } 
        
        / ** 
         * Deserializa correctamente
        private void readObject (ObjectInputStream s) arroja IOException, ClassNotFoundException { 
            s.defaultReadObject (); 
            setState (0); // restablecer al estado desbloqueado 
        } 
    } 

    / ** 
     * El objeto de sincronización hace todo el trabajo duro. Lo esperamos 
     * / 
    private final Sync sync = new Sync (); 

    @Override 
    public void lock () { 
        sync.acquire (1); 
    } 

    @Override 
    public boolean tryLock () { 
        return sync.tryAcquire (1); 
    } 

    @ Override 
    public void unlock () { 
        sync.release (1); 
    } 

    @Override 
    condición pública newCondition () {
        return sync.newCondition (); 
    } 

    public boolean isLocked () { 
        return sync.isHeldExclusively (); 
    } 

    public boolean hasQueuedThreads () { 
        return sync.hasQueuedThreads (); 
    } 

    @Override 
    public void lockInterruptibly () lanza InterruptedException { 
        sync.acquireInterruptbly (1); 
    } 

    @Override 
    public boolean tryLock (tiempo de espera largo, unidad TimeUnit) lanza InterruptedException { 
        return sync.tryAcquireNanos (1, unit.toNanos (tiempo de espera)); 
    } 
}

      Esta es una clase de pestillo similar a CountDownLatch, excepto que solo es necesario activar una única señal. Dado que el pestillo no es exclusivo, utiliza métodos de adquisición y liberación compartidos

class BooleanLatch { 

    sincronización de clase estática privada extiende AbstractQueuedSynchronizer { 
        boolean isSignalled () { 
            return getState ()! = 0; 
        } 

        @Override 
        protected int tryAcquireShared (int ignore) { 
            return isSignalled ()? 1: -1; 
        } 

        @Override 
        protected boolean tryReleaseShared (int ignore) { 
            setState (1); 
            devuelve verdadero; 
        } 
    } 

    Sincronización final privada sync = new Sync (); 

    public boolean isSignalled () { 
        return sync.isSignalled (); 
    } 

    señal de vacío público () {
        sync.releaseShared (1); 
    }

    public void await () lanza InterruptedException { 
        sync.acquireSharedInterruptiblemente (1); 
    } 
}

 

 

Supongo que te gusta

Origin blog.csdn.net/sinat_33472737/article/details/105635875
Recomendado
Clasificación