Você está na página 1de 9

UNIVERSIDAD NACIONAL DE SAN

AGUSTIN

Curso: Sistemas Operativos


El problema del lector - escritor usando
semforos
Profesor: Freddy Orlando Gonzales Saji

Alumnos:
Diego Ranilla Gallegos
Ruben Huanca Morales
Vidal Soncco Merma

2015
El problema del lector escritor Usando semforos
Un semforo sirve para controlar el nmero de hilos que acceden a la variable
compartida, en este caso el libro. Si inicializamos el semforo a 1 se comportar como
un semforo binario, aunque tambin lo podemos inicializar por ejemplo a 15, para
gestionar adecuadamente los permisos que le queramos otorgar.
Un semforo puede ser liberado por otro proceso, en los locks deben ser liberados por el
mismo proceso.

Caractersticas:
Para el lector:
Si hay escritores activos o en espera, este lector tiene que esperar (los escritores
tienen prioridad).
De otra manera, este lector puede leer (posiblemente con otros lectores)
Cuando el ltimo lector termina, si hay escritores esperando, este ltimo lector
debe llamar a uno de ellos.
Para el escritor:
Si hay lectores o escritores activos, este escritor tiene que esperar (cada uno
tiene que terminar antes que el escritor pueda actualizar la base de datos).
De otra manera, este escritor puede escribir (y tiene exclusivo acceso a la base
de datos).
Cuando el escritor termina:
1. Si hay escritores esperando, debe llamar uno (escritores tienen
prioridad).
2. Si hay solamente lectores esperando, debe llamar uno.
Interfaz:

Cdigo:
Lector.java
La clase lector se encargar de leer el libro, varios lectores pueden el mismo libro
simultneamente.
El mtodo run se ejecutar mientras que el libro no est terminado. La funcionalidad es
la que se pide en el enunciado, con cada accin llamamos a gestion.parar por si hemos
pulsado el botn de pausa.
package semaforos;
public class Lector extends Thread {
private int identLector;
private Libro libro;
private Gestion gestion;
public Lector(int identLector, Libro libro, Gestion gestion) {
this.identLector = identLector;
this.libro = libro;
this.gestion = gestion;
}
private void Esperar(int min, int max) {
try {
sleep(min + (int) (max * Math.random()));
} catch (Exception e) {
}
}
@Override
public void run() {

while (libro.libroTerminado() == false) {


gestion.parar();
Esperar(1000, 1000);
gestion.parar();
libro.leerLibro(identLector);
gestion.parar();
Esperar(500, 1000);
gestion.parar();
libro.terminarLeer(identLector);
}
}
}

Escritor.java
La clase escritor slo podr escribir el libro de 1 en 1 ya que estamos en una regin
crtica con variables compartidas tal y como pone el enunciado.
package semaforos;
public class Escritor extends Thread {
private int identEscritor;
private Libro libro;
private Gestion gestion;
public Escritor(int identEscritor, Libro libro, Gestion gestion) {
this.identEscritor = identEscritor;
this.libro = libro;
this.gestion = gestion;
}
private void Esperar(int min, int max) {
try {
sleep(min + (int) (max * Math.random()));
} catch (Exception e) {
}
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
gestion.parar();
Esperar(1000, 1000);
gestion.parar();
libro.escribirLibro(identEscritor);
gestion.parar();
Esperar(100, 0);
libro.terminarEscribir(identEscritor);
}
}
}

Libro.java
Esta clase libro es la variable compartida y por tanto, la que tenemos que proteger de
lectores/escritores para que el programa funcione satisfactoriamente.

Creamos todos los atributos necesarios para que el programa funcione, incluyendo los
locks para gestionar la entrada y salida de los escritores.
package semaforos;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Libro {
private String libro;
private Interfaz interfaz;
private int lecturas;
private Semaphore semaforoA;
public Libro(Interfaz interfaz, Semaphore semaforo) {
this.interfaz = interfaz;
libro = "";
lecturas = 0;
semaforoA = semaforo;
}
public void leerLibro(int identificador) {
try {
semaforoA.acquire();
} catch (InterruptedException ex) {
Logger.getLogger(Libro.class.getName()).log(Level.SEVERE, null, ex);
}
interfaz.meterDatos(1, interfaz.leerDatos(1) + "" + identificador + " ");
lecturas++;
}
public boolean libroTerminado() {
if (libro.length() == 50) {
return true;
} else {
return false;
}
}
public void terminarLeer(int identificador) {
interfaz.meterDatos(1, interfaz.leerDatos(1).replaceAll("" + identificador + " ", ""));
if (libroTerminado()) {
interfaz.meterDatos(4, interfaz.leerDatos(4) + "Leido por " + identificador + ": " + libro + "\n");
}
semaforoA.release();
}
public void escribirLibro(int identificador) {
try {
semaforoA.acquire(15);
} catch (InterruptedException ex) {
Logger.getLogger(Libro.class.getName()).log(Level.SEVERE, null, ex);
}
libro = libro + identificador;
interfaz.meterDatos(2, interfaz.leerDatos(2) + identificador);
interfaz.meterDatos(3, libro);

}
public void terminarEscribir(int identificador) {
interfaz.meterDatos(2, interfaz.leerDatos(2).replaceAll("" + identificador, ""));
semaforoA.release(15);
}
}

Gestion.java
Esta clase es la que gestiona los botones de reanudar y parar.
Si pulsamos el botn reanudar pondremos pausar a falso y el programa, liberamos el
semforo.
Si pulsamos el botn detener, pondremos pausar a true y activaremos el semforo.
Analizamos la condicion de pausar. Si es true activamos el semforo y continuacin lo
liberamos.
package semaforos;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Gestion {
private Semaphore semaforo;
public boolean pausar;
public Gestion() {
semaforo = new Semaphore(1, true);
}
public void reanudar() {
pausar = false;
semaforo.release();
}
public void detener() {
try {
semaforo.acquire();
pausar = true;
} catch (InterruptedException ex) {
Logger.getLogger(Gestion.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void parar() {
if (pausar) {
try {
semaforo.acquire();
} catch (InterruptedException ex) {
Logger.getLogger(Gestion.class.getName()).log(Level.SEVERE, null, ex);
}
semaforo.release();
}
}
}

Interfaz.java
Programa principal y el que ejecuta todos los hilos concurrentemente.
Creamos un nuevo objeto Gestion para reanudar y parar el sistema.
En el botn de reanudar, procedemos a habilitar el botn detener y a deshabilitar el
botn reanudar (que ya ha sido pulsado). A continuacin, reanudamos el sistema
llamando a "gestin".
En el botn de detener, procedemos a habilitar el botn reanudar y a deshabilitar el
botn detener (que ya ha sido pulsado). A continuacin, detenemos el sistema llamando
a "gestin".
La clase meterDatos introduce los datos en el jTextField, recibimos un nmero de otra
clase para saber dnde debemos introducir la informacin.
Gracias al switch podremos introducir fcilmente los datos en el jTextField correcto. Al
ser void, no devuelve nada.
La clase leerDatos devuelve un String con el contenido del jTextField. Dependiendo del
nmero pasado por parmetro leeremos un jTextField u otro. Si no se corresponde con
ninguno, devolvemos cadena vaca.
package semaforos;
import java.util.concurrent.Semaphore;
public class Interfaz extends javax.swing.JFrame {
public Interfaz() {
initComponents();
}
public Gestion gestion = new Gestion();
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
}// </editor-fold>
{

private void reanudarActionPerformed(java.awt.event.ActionEvent evt)

detener.setEnabled(true);
reanudar.setEnabled(false);
gestion.reanudar();

private void detenerActionPerformed(java.awt.event.ActionEvent evt) {


reanudar.setEnabled(true);
detener.setEnabled(false);
gestion.detener();
}
private void jTextField2ActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling code here:
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override

public void run() {


Interfaz interfaz = new Interfaz();
interfaz.setVisible(true);
interfaz.reanudar.setEnabled(false);
Semaphore semaforo = new Semaphore (15, true);

}
});

Libro libro = new Libro(interfaz, semaforo );


for (int i = 20; i < 35; i++) {
Lector l1 = new Lector(i, libro, interfaz.gestion);
l1.start();
}
for (int i = 0; i < 10; i++) {
Escritor e1 = new Escritor(i, libro, interfaz.gestion);
e1.start();
}

public void meterDatos(int i, String datos) {


switch (i) {
case 1: {
jTextField1.setText(datos);
break;
}
case 2: {
jTextField2.setText(datos);
break;
}
case 3: {
jTextField3.setText(datos);
break;
}
case 4: {
jTextArea1.setText(datos);
break;
}
}
}
public String leerDatos(int i) {
switch (i) {
case 1:
return jTextField1.getText();
case 2:
return jTextField2.getText();
case 3:
return jTextField3.getText();
case 4:
return jTextArea1.getText();
default:
return "";
}
}
}

Si el libro ha llegado a 50 habremos terminado de leer y devolvemos un valor booleano.

Você também pode gostar