Ejercicio Java
En este ejercicio, crearás un programa en Java que demuestre el uso de **sincronización** y **concurrencia** para manejar el acceso a recursos compartidos entre varios hilos. Utilizarás el mecanismo `synchronized` para garantizar que solo un hilo a la vez pueda acceder a los métodos críticos. Además, aprenderás cómo usar los métodos `wait()` y `notify()` para coordinar la ejecución de los hilos y permitir la comunicación entre ellos.
Instrucciones:
- Crea una clase llamada
CuentaBancaria
que tenga un saldo compartido entre varios hilos.
- Define un método
depositar
y un método retirar
, ambos sincronizados con synchronized
para evitar que dos hilos modifiquen el saldo simultáneamente.
- Utiliza los métodos
wait()
y notify()
para gestionar las condiciones de espera y notificación entre hilos cuando el saldo sea insuficiente para retirar dinero.
- En el método principal, crea varios hilos que simulen depósitos y retiros, y demuestra cómo la sincronización y la concurrencia permiten el acceso seguro al recurso compartido.
Este ejercicio te ayudará a comprender cómo gestionar múltiples hilos en Java, asegurando que los recursos compartidos se manejen de manera segura y eficiente, evitando problemas de concurrencia como las condiciones de carrera.
Ver código de ejemplo
// Clase CuentaBancaria que simula operaciones de depósito y retiro con sincronización
class CuentaBancaria {
private double saldo = 1000; // saldo inicial
// Método sincronizado para depositar dinero
public synchronized void depositar(double cantidad) {
saldo += cantidad;
System.out.println("Depositado: " + cantidad + ", Nuevo saldo: " + saldo);
notify(); // Notificar si algún hilo está esperando
}
// Método sincronizado para retirar dinero
public synchronized void retirar(double cantidad) throws InterruptedException {
while (saldo < cantidad) {
System.out.println("Saldo insuficiente para retirar: " + cantidad + ". Esperando...");
wait(); // Esperar hasta que haya suficiente saldo
}
saldo -= cantidad;
System.out.println("Retirado: " + cantidad + ", Nuevo saldo: " + saldo);
}
}
public class Main {
public static void main(String[] args) {
CuentaBancaria cuenta = new CuentaBancaria();
// Crear un hilo para realizar un depósito
Thread depositador = new Thread(() -> {
cuenta.depositar(500);
});
// Crear un hilo para realizar un retiro
Thread retirador = new Thread(() -> {
try {
cuenta.retirar(1200); // Intentar retirar más de lo que hay en la cuenta
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Iniciar los hilos
depositador.start();
retirador.start();
// Esperar a que ambos hilos terminen
try {
depositador.join();
retirador.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Salida:
Saldo insuficiente para retirar: 1200. Esperando...
Depositado: 500.0, Nuevo saldo: 1500.0
Retirado: 1200.0, Nuevo saldo: 300.0
Este programa demuestra cómo se manejan los problemas de concurrencia en Java utilizando sincronización. La clase CuentaBancaria
tiene dos métodos sincronizados: depositar
y retirar
. El hilo que realiza el retiro esperará si el saldo es insuficiente, mientras que el hilo de depósito notificará a los hilos en espera una vez que haya suficiente saldo. Esto muestra cómo la sincronización y los mecanismos de comunicación entre hilos (como wait()
y notify()
) pueden resolver problemas de acceso concurrente a recursos compartidos.