Control de la concurrencia en Java (API alto nivel)

Disponible a partir de Java 5, mejoras respecto a los mecanismos previos de control de la concurrencia.

  • Generan menos sobrecarga en tiempo de ejecución
  • Permiten controlar la e.m. y la sincronización a un nivel más fino
  • Soporta primitivas clásicas como los semáforos o las variables de condición en monitores
  • Ofrece cerrojos con mejor soporte a granularidad y al ámbito de uso

API java.util.concurrent.atomic

Conjunto de clases que soportan programación concurrente segura sobre variables simples tratadas de forma atómica.

Clases: AtomicBoolean, AtomicInteger, AtomicIntegerArray, AtomicLong, AtomicLongArray, AtomicReference<V>, etc

OJO, no todos los métodos del API de estas clases soportan concurrencia segura. Sólo aquellos en los que se indica que la operación se realiza de forma atómica

La clase Semaphore

Permite disponer de semáforos de conteo de semántica mínima o igual a la estándar de Dijkstra, o aumentada.

Métodos principales

  • Semaphore(long permits)
  • acquire(), acquire(int permits), equivale a wait
  • release(), release(long permits), equivale a signal
  • tryAcquire(), varias versiones
  • availablePermits()

La clase CyclicBarrier

Una barrera es un punto de espera a partir del cuál todos los hilos se sincronizan. Ningún hilo pasará por la barrera hasta que todos los hilos esperados llegan a ella.

Nos pertmite unificar resultados parciales e iniciar la siguiente fase de una ejecución simutánea.

API java.util.concurrent.locks

Proporciona clases para establecer sincronización de hilos alternativas a los bloques de código sincronizado y a los monitores.

Clases e interfaces de interés

  • ReentrantLock, proporciona cerrojos de e.m. de semántica equivalente a synchronized, pero con un manejo más sencillo y una mejor granularidad

  • LockSupport, proporciona primitivas de bloqueo de hilos que permiten al programador diseñar sus clases de sincronización y cerrojos propios

  • Condition, es una interfaz cuyas instancias se usan asociadas a locks. Implementan variables de condición y proporcionan una alternativa de sincronización a los métodos wait, notify y notifyAll de la clase Object

API de la clase ReentrantLock

Proporciona cerrojos reentrantes de semántica equivalente a synchronized.

Métodos:

lock(), unlock(), isLocked()

Métododo Condition newCondition() retorna una variable de condición asociada al cerrojo.

Interfaz Condition

Proporciona variables de condición, se usa asociada a un cerrojo, siendo cerrojo una instancia de la clase ReentrantLock

cerrojo.newCondition() retorna la variable de condición.

Métodos sobre las variables de condición:

await(), signal(), signalAll()

Clases contenedoras sincronizadas

A partir de Java 5 se incorporan versiones sincronizadas de las principales clases contenedoras.

Clases: ConcurrentHashMap, ConcurrentSkipListMap, ConcurrentSkipListSet, CopyOnWriteArrayList y CopyOnWriteArraySet.

Colas sincronizadas

A partir de Java 5 se incorporan diferentes versiones de colas, todas ellas sincronizadas.

Clases: LinkedBlockingQueue, ArrayBlockingQueue, SynchronousQueue, PriorityBlockingQueue y DelayQueue

Características

Son seguras frente a hilos concurrentes, proporcionan notificación a hilos según cambia su contenido.

Son autosincronizadas, proveen sincronización (además de e.m.) por sí mismas.

Facilitan enormemente la programación de patrones de concurrencia como el P-S.

Uso correcto de colecciones

Usamos colecciones a través de interfaces (usabilidad del código)

Colecciones no sincronizadas no mejora mucho el rendimiento, para problemas como productor-consumidor: use colas.

Minimice la sincronización explícita, si con una colección retarda sus algoritmos, distribuya los datos y use varias.