prac_3: sincronizacion con notify y notify all y wait

Anuncio
Benemérita Universidad Autónoma del
Estado de Puebla
Facultad de Cs. De la Computación
Programación Concurrente y Paralela
Práctica de Laboratorio No. 3
Profr:
María del Carmen Cerón Garnica
Alumno:
Roberto Alejandro Bravo Arredondo
Matricula:
200824268
08 de septiembre de 2011
Introducción
En esta práctica observaremos la sincronización de los hilos, mediante el método
Synchronized, y mediante la función wait() que sirve para que dos o más hilos no
accedan al mismo recurso al mismo tiempo, osea que los hilos que llamen a esta
función serán puestos en la cola de hilos bloqueados, también veremos la función
notify(), notifyAll() que sirve para que el hilo que la llamo pase a la cola de hilos
preparados.
Objetivo
Esta práctica nos ayudara a entender la excusión mutua y los mecanismos de
sincronización para los hilos.
Código
Programa Cajero Automático;
1. Identifica el problema que se está resolviendo y recurso compartido
R= Se está resolviendo el problema de un cajero automático con $10,000 de
dinero inicial, el cual es e Recurso Compartido. El cliente1 y el cliente2 hacen
retiros e ingresos respectivamente, la cuestión es que ambos no pueden ingresar
al mismo tiempo al dinero ya que podría haber incoherencias en la cuenta, y otra
condición es que la cuenta no puede sobrepasar los $10,000 que es el saldo
inicial, ni tampoco, por obvias razones, puede descender de $0.
2. ¿Qué métodos se utilizan para la sincronización?
R= Se utilizan los métodos Sinchronized, wait(), notify() y sleep().
3. Solo se tiene dos clientes, agrega otro cliente y explica que sucede en el
programa
R= Si agrego un Cliente3 si éste ingresa dinero la cuenta se bloquea porque ésta
excede la condición de no sobrepasar los $10,000, pero si lo pongo a retirar el
Cliente3 no tiene problemas en su ejecución ya que inicialmente la cuenta tiene
$10,000 y los retiros e ingresos son en un rango de $1,000, entonces es más difícil
que retirando la cuenta llegue a $0 en 5 transacciones por cliente.
4. Explica si este programa cumple con los principios de la concurrencia
R= Si cumple ya que funciona independientemente de si lo ejecutamos en un
sistema monoprocesador o en un sistema multiprocesador, y como mencioné
anteriormente el recurso compartido, que es el dinero, no puede ser accesado por
ambos al mismo tiempo, así es que el programa cumple con los principios de la
concurrencia.
5. Agrega el método de consultar saldo.
El método consultaSaldo() primero verifica las condiciones si es que la cantidad de
dinero en la Cuenta no sobrepasa los $10,000 ó está por debajo de los $0, si solo
una de las condiciones se cumple entonces el hilo entra y se pone en cola de hilos
en cola de bloqueados, sino el hilo se sigue ejecutado, realiza la consulta, la
muestra en pantalla y se pone en la cola de hilos preparados hasta la siguiente
acción.
public synchronized void consultaSaldo()
{
while (cantidad>=10000 || cantidad<=0)
{
try
{
wait();
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
System.out.println("Su Saldo Disponible es de: $"+cantidad);
notify();
}
Código completo:
import java.io.*;
class cajeroautomatico
{
public static int cont=1;
public static void main (String []args)
{
cajero caja=new cajero();
cliente1 c1=new cliente1(caja);
cliente2 c2=new cliente2(caja);
cliente3 c3=new cliente3(caja);
c1.start();
c2.start();
c3.start();
}
}
public class cliente1 extends Thread
{
private cajero caja1;
public cliente1 (cajero x)
{
this.caja1=x;
}
public void run()
{
int cantidad;
for (int i=0; i<5; i++)
{
do
{
cantidad=((int)(Math.random()*1000));
}while (cantidad<1 || cantidad>1000);
System.out.println ((cajeroautomatico.cont++)+": Cliente1 Retirando:
$"+cantidad);
caja1.retira(cantidad);
caja1.consultaSaldo();
try
{
sleep ((int)(Math.random()*1000));
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
}
}
public class cliente2 extends Thread
{
private cajero caja1;
public cliente2 (cajero x)
{
this.caja1=x;
}
public void run()
{
int cantidad;
for (int i=0; i<5; i++)
{
do
{
cantidad=((int)(Math.random()*1000));
}while (cantidad<1 || cantidad>1000);
System.out.println ((cajeroautomatico.cont++)+": Cliente2 Ingresando:
$"+cantidad);
caja1.ingresar(cantidad);
//caja1.consultaSaldo();
try
{
sleep ((int)(Math.random()*1000));
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
}
}
public class cliente3 extends Thread
{
private cajero caja1;
public cliente3 (cajero x)
{
this.caja1=x;
}
public void run()
{
int cantidad;
for (int i=0; i<5; i++)
{
do
{
cantidad=((int)(Math.random()*1000));
}while (cantidad<1 || cantidad>1000);
System.out.println ((cajeroautomatico.cont++)+": Cliente3 Ingresando:
$"+cantidad);
caja1.ingresar(cantidad);
//System.out.println ((cajeroautomatico.cont++)+": Cliente3 Retirando:
$"+cantidad);
//caja1.retira(cantidad);
try
{
sleep ((int)(Math.random()*1000));
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
}
}
public class cajero
{
private int cantidad;
public cajero()
{
cantidad=10000;
}
public synchronized void retira(int x)
{
while (cantidad-x <= 0) //Si la condicion es Cierta el Hilo se bloquea y pasa a
esperar
{
try
{
wait(); // Esta funcion libera la e.m sobre el monitor(Constructor) y
encola al hilo que llamó al método
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
// Si la condicion es falsa el hilo sigue la ejecucion.
//System.out.println("Cantidad antes de retirar: $"+cantidad);
cantidad=cantidad-x;
//System.out.println("Cantidad despues de retirar: $"+cantidad);
notifyAll(); //Esta funcion pone al hilo en la cola de Hilos Preparados y se
reanudara cuando sea planificado
}
public synchronized void ingresar(int x)
{
while (cantidad+x >= 10000)
{
try
{
System.out.println("* Imposible ingresar cantidad, la cuenta
excedería el monto permitido...");
cantidad=cantidad-x;
wait();
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
//System.out.println("Cantidad antes de ingresar: $"+cantidad);
cantidad=cantidad+x;
//System.out.println("Cantidad despues de ingresar: $"+cantidad);
notifyAll();
}
public synchronized void consultaSaldo()
{
while (cantidad>=10000 || cantidad<=0)
{
try
{
wait();
}
catch (InterruptedException e)
{
System.err.println ("Error"+e.toString());
}
}
System.out.println("Su Saldo Disponible es de: $"+cantidad);
notifyAll();
}
}
Conclusión
En esta práctica aprendí mucho sobre la sincronización de los hilos, sobre el cómo
hacerlos esperar en la cola de bloqueados si se cumple una condición o
simplemente hacerles un notify() y dejarlos en la cola de hilos preparados para
ejecución. También el cómo utilizar el método Sinchronized para cumplir la
exclusión mutua y que no haya incoherencias en los recursos compartidos.
Reflexión Personal
Puedo decir como reflexión que el programa de Cajero me fue un poco complicado
entender ya que había métodos que no conocía, pero haciendo pruebas y leyendo
en las notas proporcionadas logre entender apropiadamente cada método y
hacerlo funcionar de la manera que deseo.
Descargar