"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Técnicas para gestionar la concurrencia en Java utilizando semáforos

Técnicas para gestionar la concurrencia en Java utilizando semáforos

Publicado el 2024-11-09
Navegar:148

1. ¿Qué es un semáforo en Java?

Techniques for Managing Concurrency in Java Using Semaphores

Un semáforo en Java es una ayuda de sincronización que restringe la cantidad de subprocesos que pueden acceder a un recurso compartido en un momento dado. Es parte del paquete java.util.concurrent y se utiliza para administrar el acceso simultáneo a recursos, como archivos, bases de datos o conexiones de red.

1.1 ¿Cómo funciona un semáforo?

Techniques for Managing Concurrency in Java Using Semaphores

Un semáforo controla el acceso a un número determinado de permisos. Cada permiso representa el derecho a acceder a un recurso en particular. El semáforo realiza un seguimiento de la cantidad de permisos disponibles, lo que determina cuántos subprocesos pueden acceder al recurso simultáneamente.

Permiso: un token o ticket que permite que un hilo continúe accediendo a un recurso compartido.

Cuando creas un semáforo, especificas el número de permisos disponibles. Este número define cuántos subprocesos pueden acceder al recurso simultáneamente.

Antes de que un hilo pueda acceder al recurso, debe adquirir un permiso del semáforo. Esto se hace usando el método adquirir().

Adquirir: este método se llama cuando un hilo quiere acceder al recurso. Si hay un permiso disponible, el semáforo disminuye el número de permisos disponibles y permite que el hilo continúe. Si no hay permisos disponibles, el hilo se bloquea hasta que haya un permiso disponible.

Comportamiento de bloqueo: si no hay permisos disponibles, el subproceso que llama a adquirir() se bloqueará (es decir, esperará) hasta que otro subproceso libere un permiso.

Una vez que un hilo ha terminado de usar el recurso, debe liberar el permiso para que esté disponible para otros hilos. Esto se hace usando el método release().

Release: este método incrementa la cantidad de permisos disponibles. Si hay hilos esperando un permiso, uno de ellos será desbloqueado y se le permitirá adquirir el permiso.

1.2 Tipos de semáforos

Hay dos tipos de semáforos en Java:

  • Semáforo de conteo: este tipo de semáforo permite que un número determinado de subprocesos accedan a un recurso. Por ejemplo, si configura el semáforo en 3, solo tres subprocesos podrán acceder al recurso al mismo tiempo.
  • Semáforo binario (Mutex): Este es un caso especial de conteo de semáforo donde el número de permisos es uno, lo que permite que solo un subproceso acceda al recurso a la vez. A menudo se utiliza como bloqueo de exclusión mutua (mutex).

2. Implementación de semáforos en Java

Para comprender mejor cómo funcionan los semáforos, veamos una implementación práctica. Crearemos un escenario simple en el que varios subprocesos intentan acceder a un recurso limitado.

2.1 Configuración del entorno

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {

    // Creating a semaphore with 3 permits
    private static final Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        // Creating and starting 6 threads
        for (int i = 1; i 



2.2 Explicación del Código

En este ejemplo, creamos un semáforo con tres permisos, lo que significa que solo tres subprocesos pueden acceder a la sección crítica del código en un momento dado. Luego creamos seis subprocesos, todos los cuales intentan adquirir un permiso. Una vez que un hilo adquiere un permiso, simula algún trabajo durmiendo durante dos segundos antes de liberar el permiso.

2.3 Observando la salida

Cuando ejecute el código anterior, el resultado se verá así:

Worker 1 is trying to acquire a permit...
Worker 1 acquired a permit.
Worker 2 is trying to acquire a permit...
Worker 2 acquired a permit.
Worker 3 is trying to acquire a permit...
Worker 3 acquired a permit.
Worker 4 is trying to acquire a permit...
Worker 5 is trying to acquire a permit...
Worker 6 is trying to acquire a permit...
Worker 1 is releasing a permit.
Worker 4 acquired a permit.
Worker 2 is releasing a permit.
Worker 5 acquired a permit.
Worker 3 is releasing a permit.
Worker 6 acquired a permit.

Aquí, los primeros tres hilos adquieren exitosamente los permisos y comienzan sus tareas. Los subprocesos restantes deben esperar hasta que se emita un permiso antes de poder continuar.

2.4 Casos de uso prácticos

Los semáforos son particularmente útiles en escenarios donde es necesario limitar la cantidad de accesos simultáneos a un recurso en particular, como por ejemplo:

  • Limitar conexiones a bases de datos
  • Controlar el acceso a un archivo compartido
  • Administrar conexiones de red en un servidor

3. Ventajas y desventajas del uso de semáforos

Si bien los semáforos son una herramienta poderosa, tienen su propio conjunto de ventajas y desventajas.

3.1 Ventajas

Flexibilidad: los semáforos permiten un control preciso sobre el acceso a los recursos por parte de múltiples subprocesos.

Escalabilidad: los semáforos pueden gestionar fácilmente el acceso a una gran cantidad de recursos.

Equidad: los semáforos se pueden configurar para garantizar que los subprocesos adquieran permisos de manera justa.

3.2 Desventajas

Complejidad: el uso de semáforos puede introducir complejidad en el código, lo que dificulta la depuración.

Interbloqueos: si no se manejan correctamente, los semáforos pueden provocar interbloqueos en los que los subprocesos quedan bloqueados indefinidamente en espera de permisos.

4. Mejores prácticas para utilizar semáforos en Java

Para evitar errores comunes y aprovechar al máximo los semáforos, considere las siguientes mejores prácticas:

4.1 Utilice tryAcquire para adquisiciones por tiempo limitado

En lugar de usar adquirir(), que bloquea indefinidamente, puedes usar tryAcquire() para intentar adquirir un permiso con un tiempo de espera. Esto evita que los hilos se queden atascados en espera.

if(semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
    try {
        // Critical section
    } finally {
        semaphore.release();
    }
}

4.2 Liberar siempre permisos en un bloque finalmente

Para evitar fugas de recursos, libere siempre el permiso en un bloque finalmente. Esto garantiza que el permiso se libere incluso si ocurre una excepción.

4.3 Evite el uso de semáforos para cerraduras simples

Si solo necesita bloquear y desbloquear un recurso para un solo subproceso, considere usar ReentrantLock o sincronizado en lugar de un semáforo binario.

5. Conclusión

Los semáforos son una herramienta poderosa para administrar la concurrencia en Java, lo que le permite controlar la cantidad de subprocesos que acceden a un recurso compartido. Si sigue las técnicas y mejores prácticas descritas en este artículo, podrá implementar semáforos de forma eficaz en sus aplicaciones Java para garantizar una gestión de recursos segura y eficiente.

Si tienes alguna pregunta o te gustaría compartir tus propias experiencias con los semáforos, ¡no dudes en comentar a continuación!

Lea más publicaciones en: Técnicas para gestionar la concurrencia en Java utilizando semáforos

Declaración de liberación Este artículo se reproduce en: https://dev.to/anh_trntun_4732cf3d299/techniques-for-managing-concurrency-in-java-using-semaphores-5ai?1 Si hay alguna infracción, comuníquese con [email protected] para eliminar él
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3