2010-07-22 10 views

Respuesta

13

Si está hablando sobre el uso de un mecanismo de bloqueo (o incluso barreras de sincronización) solo use un java.util.concurrent.Lock. La sugerencia obvia es utilizar el ReentrantLock que delega a Synch. La sincronización es un AQS que a su vez usa LockSupport.

Todo está hecho debajo de las fundas para usted.

Editar:

No vamos a ir a través de los usos prácticos de AbstractQueuedSynchronizer (AQS).

Sin embargo, las construcciones simultáneas pueden ser muy diferentes en su uso, todas pueden tener las mismas funciones subyacentes.

I.e. Bajo alguna condición, estacione este hilo. Bajo alguna otra condición, despierta un subproceso.

Este es un conjunto de instrucciones muy amplio, pero hace que sea obvio que la mayoría de las estructuras de concurrencia necesitarían alguna funcionalidad común que les permitiera manejar esas operaciones. Ingrese AQS. Hay cinco barreras principales de sincronización.

  • ReentrantLock
  • ReadLock
  • WriteLock
  • Semaphore
  • CountDownLatch

Ahora, todas estas cinco estructuras tienen muy diferente conjunto de reglas al utilizarlos. Un CountdownLatch puede permitir que muchos subprocesos se ejecuten al mismo tiempo pero obliga a uno (o más) subprocesos a esperar hasta que al menos n subprocesos cuenten hacia abajo en dicho enganche.

ReentrantLock fuerza solo un hilo a la vez para ingresar a una sección crítica y poner en cola todos los demás hilos para esperar a que se complete.

ReadLock permite cualquier cantidad de hilos de lectura en la sección crítica hasta que se obtenga un bloqueo de escritura.

Los ejemplos pueden continuar, pero el panorama general aquí es que todos usan AQS. Esto se debe a que pueden usar las funciones primitivas que AQS ofrece e implementa una funcionalidad más compleja en la parte superior. AQS le permite estacionar subprocesos de desconexión y desconexión (de forma interrumpible si es necesario) pero de forma que pueda admitir muchas funciones complejas.

+0

W.: Vi LockSupport se utiliza en 'AbstractQueuedLongSynchronizer', lo que sugiere que es una especie de clase API interna? Solo quería ver un fragmento de código ilustrativo ... – Max

+2

@Max LockSupport es una clase de utilidad que cualquiera puede usar. No es necesariamente una clase interna. Unsafe.java es un buen ejemplo de una clase interna. LockSupport es público para que otros puedan escribir su propia versión de AQS –

+0

W.: Gracias John, sé que es para la extensión. Tu respuesta me hizo reformular una pregunta: en general, el uso de 'AbstractQueuedSynchronizer' me parece impreciso. – Max

1

no son para uso directo en el código del cliente; más para ayudar a construir nuevas clases concurrentes.

1

AQS es una clase maravillosa para crear primitivas de concurrencia, pero es compleja y requiere un poco de estudio para usarla correctamente. Lo he usado para algunas cosas como lazy initialisation y un simple rápido reusable latch.

Tan complejo como es, no creo que AQS sea particularmente vago, tiene excelentes javadocs que describen cómo usarlo correctamente.

+0

¿Exactamente qué es AQS? – Pacerier

+0

java.util.concurrent.AbstractQueuedSynchronizer –

+0

en realidad: java.util.concurrent.locks.AbstractQueuedSynchronizer –

0

AFAIK, AbstractQueuedSynchronizer se utiliza para administrar las transiciones de estado. El JDK lo usa para extender Sync, una clase interna para java.util.concurrent.FutureTask. La clase Sync administra los estados (LISTO, EN EJECUCIÓN, RAN y CANCELADO) de FutureTask y las transiciones entre ellos.

Esto permite, como ya sabrá, que FutureTask bloquee en FutureTask.get() hasta que se llegue al estado de RAN, por ejemplo.

Cuestiones relacionadas