Semáforos en JAVA

En este post hablaremos de programación Concurrente con Semaforos.

En este post (Trabajar con monitores en JAVA) ya hablamos de Threads, monitores y formas de sincronización, si no sabéis lo que son, podéis pasaros a echar un vistazo.

Que son semaforos

Un semáforo es una variable especial (o tipo abstracto de datos) que constituye el método clásico para restringir o permitir el acceso a recursos compartidos (por ejemplo, un recurso de almacenamiento del sistema o variables del código fuente) en un entorno de multiprocesamiento (en el que se ejecutarán varios procesos concurrentemente). Fueron inventados por Edsger Dijkstra en 1965 y se usaron por primera vez en el sistema operativo THEOS.

La verificación y modificación del valor, así como la posibilidad de irse a dormir (bloquerse) se realiza en conjunto, como una sola e indivisible acción atómica. El sistema operativo garantiza que al iniciar una operación con un semáforo, ningún otro proceso puede tener acceso al semáforo hasta que la operación termine o se bloquee. Esta atomicidad es absolutamente esencial para resolver los problemas de sincronización y evitar condiciones de competencia.

Si hay n recursos, se inicializará el semáforo al número n. Así, cada proceso, al ir solicitando un recurso, verificará que el valor del semáforo sea mayor de 0; si es así es que existen recursos libres, seguidamente acaparará el recurso y decrementará el valor del semáforo.

Cuando el semáforo alcance el valor 0, significará que todos los recursos están siendo utilizados, y los procesos que quieran solicitar un recurso deberán esperar a que el semáforo sea positivo.

Los semáforos se emplean para permitir el acceso a diferentes partes de programas (llamados secciones críticas) donde se manipulan variables o recursos que deben ser accedidos de forma especial. Según el valor con que son inicializados se permiten a más o menos procesos utilizar el recurso de forma simultánea.

Un tipo simple de semáforo es el binario, que puede tomar solamente los valores 0 y 1. Se inicializan en 1 y son usados cuando sólo un proceso puede acceder a un recurso a la vez. Se les suele llamar mutex.

Los semáforos pueden ser usados para diferentes propósitos, entre ellos:

  • Implementar cierres de exclusión mutua o locks.
  • Barreras.
  • Permitir a un máximo de N threads (hilos) acceder a un recurso, inicializando el semáforo en N.
  • Notificación. Inicializando el semáforo en 0 puede usarse para comunicación entre threads sobre la disponibilidad de un recurso.

Para mas información de semáforos, visitar wikipedia.

EJEMPLO

Para este ejemplo, simularemos un sistema Productor-Consumidor y usaremos semáforos para controlar el flujo de datos.

Haremos tres clases, Almacén, Productor, y Consumidor.

En la clase Consumidor crearemos una instancia del almacén y en el método run() solo llamaremos al método consumir() de este.

La clase Productor será parecida, solo que llamaremos al método producir().

En la clase Almacen definiremos un limite máximo de productos a almacenar y declararemos los 3 semáforos, el productor, el consumidor y un mutex.

En el método producir(), daremos permisos al semáforo productor y al mutex, aumentaremos los productos y liberaremos los permisos del mutex y del semáforo consumidor (para que pueda empezar a consumir).

El método consumir() es parecido. Daremos permisos al consumidor y mutex, restaremos los productos y liberaremos el mutex y el productor (para que pueda trabajar).

En el main() principal iniciaremos con un bucle los productores y los consumidores.

El código completo está en : PSP_Productor_Consumidor.

Y tenéis más ejemplos en: PSP_Datos_Sensor, PSP_Lector_Escritor_Semaforos, PSP_GrafoProcedencias, PSP_Registro_Lluvias.

Deja un comentario

Diseña un sitio como este con WordPress.com
Comenzar