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.