0% encontró este documento útil (0 votos)
12 vistas5 páginas

Programación Concurrente

El documento describe la implementación de concurrencia en Java utilizando semáforos y mutex, destacando su uso en el patrón productor-consumidor. Se explica cómo los productores y consumidores interactúan a través de una clase común que gestiona una cola de espera y controla el acceso mediante semáforos y bloqueos. Además, se detallan los métodos clave como acquire, release, y tryAcquire para gestionar permisos y evitar condiciones de carrera.

Cargado por

k2a.c3dd
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
12 vistas5 páginas

Programación Concurrente

El documento describe la implementación de concurrencia en Java utilizando semáforos y mutex, destacando su uso en el patrón productor-consumidor. Se explica cómo los productores y consumidores interactúan a través de una clase común que gestiona una cola de espera y controla el acceso mediante semáforos y bloqueos. Además, se detallan los métodos clave como acquire, release, y tryAcquire para gestionar permisos y evitar condiciones de carrera.

Cargado por

k2a.c3dd
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 5

Concurrencia:

Class Semaphore:
Tiene un contador interno que gestiona cuántos permisos hay disponibles.
Semaphore sem1 = new Semaphore(contador);
Aquire decrementa el contador (si contador != 0), mientras que release lo incrementa.
Nota: semaphore gestiona la concurrencia para sus métodos, por lo que no se debe
combinar con cosas como synchronized o mutex.
Método Qué hace

Espera hasta obtener un permiso (bloquea si no


acquire()
hay)

release() Libera un permiso (aumenta el contador)

tryAcquire() Intenta obtener un permiso sin bloquear

availablePermits() Devuelve cuántos permisos quedan disponibles

aquire: intenta conseguir un permiso. Si lo hay, empieza a ejecuter; sino, el proceso


entrante espera hasta que los haya.
tryAquire: si hay un permiso disponible, ejecuta. Sino, “se va” (el proceso no se
queda esperando, se cancela).

Mutex:
Es como Semaphore, pero con un solo permiso (dos estados, bloqueado o libre).

ReentrantLock mutex = new ReentrantLock();


Impelementaciones concurentes:

Productor-consumidor:
Una clase produce datos, otra los procesa. Debe haber una instancia intermedia
Compartida que les permita comunicarse y que almacene el recurso compartido. Se
ejecuta siguiendo los pasos listados:
1.La clase común tiene una lista donde acumula procesos que esperan. Tiene
semáforos que controlan los permisos de acceso a la lista.
2. Todos los accesos a la lista son por medio de la clase común. Entonces:
I. El productor quiere producir, pero debe asegurarse de que la lista
compartida no esté llena.
a) Si no está llena: se agrega el proceso productor a la cola de espera.
b) Si está llena: el proceso se aborta.
II. El consumidor quiere consumir, pero debe asegurarse de que la lista no
esté vacía.

public class Productor implements Runnable{


//atributos del productor
private int id;
private Compartida comp;
private semaphore atendido= new Semaphore(0); //es como un bool que dice si
el proceso puede ser atendido por el consumidor. Es u n semáforo para evitar
race conditions.
public void run(){ //el productor produce un dato
boolean puedeProducir = this.comp.intentarAtender(this); //en la clase
común, hay alguna estructura sincronizada que controla cuantos
procesos pueden esperar a la vez. intentarAtender debe hacerse
con un tryAquire e insertat this si se puede.
if(!puedeProducir){
return; //si la cola de espera está llena, el proceso se aborta.
}
else{
this.esperar(); //Si la cola no está llena, se pone el proceso en la
cola de espera
}
}
public void esperar(){ //wait
try{
this.atendido.aquire(); //pregunta si puede ser atendido. Sino,
espera.
}catch (interruptedException e){
e.printStackTrace();
}
}

public void atender(){ //libera un permiso para que el proceso pueda ser
atendido. LO MANEJA LA CLASE COMUN.
this.atendido.release();
}
}

public class Consumidor implements Runnable{


private int id;
private Compartida comp;

//constructor
public void run(){
while(true){ //Simula la espera. El consumidor está siempre disponible
para atender a un productor, pero duerme mientras espera a que un
productro entre en la cola.
Procutors siguiente = this.comp.extraerCola(); //saca el primero
de la cola de espera (FIFO) para poder ser procesado.
if(siguiente != null){
siguiente.atender(); //si la cola de espera no está vacía,
se atiende al siguiente productor.
}
else{
try{
Thread.sleep(100); //si la cola está vacía, el
consumidor duerme un tiempo antes de volver a
intentar atender un consumidor
} catch (interruptedException e){
e.printStackTrace();
}
}

}
}

n es la cantidad de procesos productores que pueden estar esperando en simultáneo. Si


hay n procesos ya esperando, se prohibe el acceso a otro nuevo.

public class Compartida{


private list<Productor> Cola = new LinkedList<>; //cola de espera. Se
gestiona su acceso mediante mutex y semáforos.

private Semaphore libres = new Semaphore(n); //modela cuantos lugares libres


quedan el la cola de espera. Lo usan los Productores para tomar permisos de
espera en la cola.
private Semaphore ocupados = new Semaphore(0); //modela cuántos procesos
están en la cola. Lo usa Consumidor para tomar un Productor para atender.

private ReentrantLock mutex = new ReentrantLock(); //mutex que se usa para


coordinar accesos concurrentes a la cola

public boolean intentarAtender(Productor p){


boolean hayLugar = libres.tryAquire();
if(!hayLugar)
return false; //si no hay lugar, el tryAquire aborta el proceso
entrante y el método retorna false.

this.mutex.lock() //se accede a la cola, por lo que se deben


bloquear los otros procesos que quieren acceder a la cola
this.Cola.add(p); //se añade el proceso entrante a la cola de
espera
this.ocupados.release(); //se libera un permiso en ocupados para
que el consumidor lo tome si lo necesita.
this.mutex.unlock();

return true;
}

public Productor extraerCola(){


try{
this.ocupados.aquire(); //intenta obtener un permiso de
ocupados. Esto es, se fija si la cola no está vacía y decrementa
el contador de ocupados
}catch (InterruptedException e){
e.printStackTrace();
}

this.mutex.lock(); //zona crítica


Productor sig = this.Cola.remove(0);
this.libres.release(); //se incrementa el contador de libres
this.mutex.unlock(); //fin de la zona crítica

return sig;
}

También podría gustarte