Sincronización y Concurrencia

En este ejercicio, aprenderás cómo manejar la **sincronización** y la **concurrencia** en Java, dos conceptos fundamentales cuando se trabaja con aplicaciones multihilo. El enfoque principal será garantizar el acceso seguro a los recursos compartidos entre hilos, utilizando mecanismos como `synchronized`, `wait()`, `notify()`, entre otros. Estos conceptos son esenciales para mejorar el rendimiento y la estabilidad de aplicaciones Java que ejecutan múltiples hilos simultáneamente.

Tema

Hilos y Concurrencia

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:

  1. Crea una clase llamada CuentaBancaria que tenga un saldo compartido entre varios hilos.
  2. Define un método depositar y un método retirar, ambos sincronizados con synchronized para evitar que dos hilos modifiquen el saldo simultáneamente.
  3. 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.
  4. 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.


// 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.


 Comparte este ejercicio JAVA