Sobes.tech
Middle+

¿Ha trabajado con semáforos en su práctica?

sobes.tech AI

Respuesta de la IA

Sí, he tenido que usar semáforos, especialmente en el contexto del trabajo con concurrencia en aplicaciones Android.

Los semáforos en Java (java.util.concurrent.Semaphore) se utilizan para limitar el número de hilos que pueden acceder simultáneamente a un recurso determinado. Esto es útil en escenarios donde el recurso tiene una "capacidad" limitada, por ejemplo, un grupo de conexiones o un número limitado de ranuras disponibles.

Los métodos principales con los que he trabajado son:

  • acquire(): Bloquea el hilo actual hasta que una autorización esté disponible.
  • acquire(int permits): Bloquea el hilo actual hasta que la cantidad especificada de permisos esté disponible.
  • release(): Devuelve una autorización al semáforo, aumentando la cantidad de permisos disponibles.
  • release(int permits): Devuelve la cantidad especificada de permisos.
  • tryAcquire(): Intenta obtener una autorización sin bloquear el hilo.
  • availablePermits(): Devuelve la cantidad actual de permisos disponibles.

Ejemplo de uso:

import java.util.concurrent.Semaphore;

public class ResourcePool {

    private static final int MAX_AVAILABLE = 5;
    private final Semaphore permits = new Semaphore(MAX_AVAILABLE, true); // Semáforo justo

    public void useResource() throws InterruptedException {
        permits.acquire(); // Solicitamos permiso
        try {
            // Lógica de uso del recurso (por ejemplo, trabajar con un grupo de conexiones)
            System.out.println(Thread.currentThread().getName() + " usando recurso.");
            Thread.sleep(1000); // Simulación de trabajo con el recurso
        } finally {
            permits.release(); // Liberamos el permiso
            System.out.println(Thread.currentThread().getName() + " terminó de usar el recurso.");
        }
    }

    public static void main(String[] args) {
        ResourcePool pool = new ResourcePool();
        // Creamos varios hilos que intentarán usar el recurso
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    pool.useResource();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

En este ejemplo, el semáforo permits se inicializa con 5 permisos, lo que significa que solo 5 hilos pueden estar dentro del bloque try que usa el recurso al mismo tiempo. El método acquire() bloquea los hilos si todos los permisos están ocupados, hasta que otros hilos llamen a release().

Los semáforos son útiles para gestionar el acceso a grupos de recursos limitados, pero hay que tener en cuenta posibles problemas como los deadlocks, si no se gestionan correctamente la obtención y liberación de permisos. Usar try con un bloque finally para llamar a release() es una buena práctica para garantizar la liberación de recursos incluso en caso de excepciones.