Ejemplos

Ejemplo 7: Condiciones de carrera en Java

En este artículo recrearemos una condición de carrera en Java utilizando un ejemplo práctico para ilustrar el concepto y las consecuencias de las condiciones de carrera en la programación concurrente.

En este artículo recrearemos una condición de carrera en Java utilizando un ejemplo práctico para ilustrar el concepto y las consecuencias de las condiciones de carrera en la programación concurrente.

Descripción del problema

Supongamos que tienes una clase Product que representa un producto en una tienda en línea. Esta clase tiene un método decreaseStock() que reduce el stock del producto en una cantidad específica. Si varios clientes intentan comprar el mismo producto al mismo tiempo, podrían ocurrir condiciones de carrera que resulten en un stock negativo o en la venta de más productos de los disponibles.

Ejemplo de código

Clase Product

public class Product {
    private String name;
    private int stock;

    public Product(String name, int stock) {
        this.name = name;
        this.stock = stock;
    }

    public void decreaseStock(int quantity) {
        if (stock >= quantity) {
            stock -= quantity;
            IO.println("Stock decreased by " + quantity + ". Remaining stock: " + stock);
        } else {
            IO.println("Not enough stock to decrease by " + quantity + ". Remaining stock: " + stock);
        }
    }

    public int getStock() {
        return stock;
    }

    public String getName() {
        return name;
    }
}

Simulación de condiciones de carrera

public class RaceConditionExample {
    void main() throws InterruptedException {
        Product product = new Product("Laptop", 10);

        Runnable purchaseTask = () -> {
            for (int i = 0; i < 5; i++) {
                product.decreaseStock(1);
            }
        };

        Thread thread1 = new Thread(purchaseTask);
        Thread thread2 = new Thread(purchaseTask);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        IO.println("Final stock: " + product.getStock());
    }
}

En este ejemplo, hemos creado una clase Product con un método decreaseStock() que reduce el stock del producto. Luego, en la clase RaceConditionExample, hemos simulado dos hilos que intentan comprar el mismo producto al mismo tiempo, lo que puede resultar en una condición de carrera. Debido a la falta de sincronización en el método decreaseStock(), es posible que el resultado final no sea el esperado, y el stock podría llegar a ser negativo o mostrar un número incorrecto de productos restantes.

Clase Product con sincronización

public class Product {
    private String name;
    private int stock;

    public Product(String name, int stock) {
        this.name = name;
        this.stock = stock;
    }

    public synchronized void decreaseStock(int quantity) {
        if (stock >= quantity) {
            stock -= quantity;
            IO.println("Stock decreased by " + quantity + ". Remaining stock: " + stock);
        } else {
            IO.println("Not enough stock to decrease by " + quantity + ". Remaining stock: " + stock);
        }
    }

    public int getStock() {
        return stock;
    }

    public String getName() {
        return name;
    }
}

En esta versión de la clase Product, hemos sincronizado el método decreaseStock() para asegurarnos de que solo un hilo pueda acceder a él a la vez. Esto evita las condiciones de carrera y garantiza que el stock se actualice correctamente, incluso cuando varios hilos intentan comprar el mismo producto simultáneamente.

Conclusión

En este artículo, hemos recreado una condición de carrera en Java utilizando un ejemplo práctico con una clase Product y un método decreaseStock(). Hemos demostrado cómo la falta de sincronización puede llevar a resultados impredecibles y cómo la sincronización adecuada puede resolver este problema, garantizando que el stock se actualice correctamente incluso en situaciones concurrentes. Es crucial entender las condiciones de carrera y aplicar las mejores prácticas de sincronización para evitar problemas en la programación concurrente.

Copyright Jesús Aurelio Castro Magaña © 2026