"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Técnicas para gerenciar simultaneidade em Java usando semáforos

Técnicas para gerenciar simultaneidade em Java usando semáforos

Publicado em 2024-11-09
Navegar:472

1. O que é um semáforo em Java?

Techniques for Managing Concurrency in Java Using Semaphores

Um semáforo em Java é um auxílio de sincronização que restringe o número de threads que podem acessar um recurso compartilhado a qualquer momento. Faz parte do pacote java.util.concurrent e é usado para gerenciar o acesso simultâneo a recursos, como arquivos, bancos de dados ou conexões de rede.

1.1 Como funciona um semáforo?

Techniques for Managing Concurrency in Java Using Semaphores

Um semáforo controla o acesso a um determinado número de licenças. Cada licença representa o direito de acesso a um recurso específico. O semáforo registra o número de permissões disponíveis, o que determina quantas threads podem acessar o recurso simultaneamente.

Permit : um token ou ticket que permite que um thread prossiga com o acesso a um recurso compartilhado.

Ao criar um semáforo, você especifica o número de licenças disponíveis. Este número define quantos threads podem acessar o recurso simultaneamente.

Antes que um thread possa acessar o recurso, ele deve adquirir uma permissão do semáforo. Isso é feito usando o método acquire().

Acquire : Este método é chamado quando um thread deseja acessar o recurso. Se uma licença estiver disponível, o semáforo diminui o número de licenças disponíveis e permite que o encadeamento prossiga. Se nenhuma permissão estiver disponível, o thread será bloqueado até que uma permissão seja disponibilizada.

Comportamento de bloqueio : Se nenhuma permissão estiver disponível, o thread que chama adquirir() será bloqueado (ou seja, irá esperar) até que outro thread libere uma permissão.

Depois que um thread terminar de usar o recurso, ele deverá liberar a permissão para disponibilizá-lo para outros threads. Isso é feito usando o método release().

Release : Este método aumenta o número de licenças disponíveis. Se houver algum thread aguardando permissão, um deles será desbloqueado e poderá adquirir a licença.

1.2 Tipos de Semáforos

Existem dois tipos de semáforos em Java:

  • Semáforo de contagem: Este tipo de semáforo permite que um determinado número de threads acesse um recurso. Por exemplo, se você definir o semáforo como 3, apenas três threads poderão acessar o recurso ao mesmo tempo.
  • Semáforo Binário (Mutex): Este é um caso especial de contagem de semáforo onde o número de permissões é um, permitindo que apenas um thread acesse o recurso por vez. É frequentemente usado como um bloqueio de exclusão mútua (mutex).

2. Implementando Semáforos em Java

Para entender melhor como funcionam os semáforos, vejamos uma implementação prática. Criaremos um cenário simples onde vários threads tentam acessar um recurso limitado.

2.1 Configurando o Ambiente

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 Explicação do Código

Neste exemplo, criamos um semáforo com três permissões, o que significa que apenas três threads podem acessar a seção crítica do código a qualquer momento. Em seguida, criamos seis threads, todos tentando adquirir uma licença. Depois que um thread adquire uma permissão, ele simula algum trabalho dormindo por dois segundos antes de liberar a permissão.

2.3 Observando o Resultado

Quando você executa o código acima, a saída será semelhante a esta:

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.

Aqui, os três primeiros threads adquirem as permissões com sucesso e iniciam suas tarefas. Os threads restantes devem esperar até que uma licença seja liberada antes de poderem prosseguir.

2.4 Casos de uso prático

Os semáforos são particularmente úteis em cenários onde você precisa limitar o número de acessos simultâneos a um recurso específico, como:

  • Limitando conexões de banco de dados
  • Controlando o acesso a um arquivo compartilhado
  • Gerenciando conexões de rede em um servidor

3. Vantagens e desvantagens do uso de semáforos

Embora os semáforos sejam uma ferramenta poderosa, eles vêm com seu próprio conjunto de vantagens e desvantagens.

3.1 Vantagens

Flexibilidade : Os semáforos permitem controle preciso sobre o acesso a recursos por vários threads.

Escalabilidade : Os semáforos podem gerenciar facilmente o acesso a um grande número de recursos.

Fairness : Os semáforos podem ser configurados para garantir que os threads adquiram licenças de maneira justa.

3.2 Desvantagens

Complexidade : o uso de semáforos pode introduzir complexidade em seu código, dificultando a depuração.

Deadlocks : Se não forem tratados corretamente, os semáforos podem levar a deadlocks onde os threads são bloqueados indefinidamente aguardando permissões.

4. Melhores práticas para usar semáforos em Java

Para evitar armadilhas comuns e aproveitar ao máximo os semáforos, considere as seguintes práticas recomendadas:

4.1 Use tryAcquire para aquisições por tempo limitado

Em vez de usar adquirir(), que bloqueia indefinidamente, você pode usar tryAcquire() para tentar adquirir uma licença com tempo limite. Isso evita que os threads fiquem presos esperando.

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

4.2 Sempre liberar permissões em um bloco final

Para evitar vazamentos de recursos, sempre libere a licença em um bloco finalmente. Isso garante que a licença seja liberada mesmo que ocorra uma exceção.

4.3 Evite usar semáforos para bloqueios simples

Se você precisar apenas bloquear e desbloquear um recurso para um único thread, considere usar ReentrantLock ou sincronizado em vez de um semáforo binário.

5. Conclusão

Semáforos são uma ferramenta poderosa para gerenciar simultaneidade em Java, permitindo controlar o número de threads que acessam um recurso compartilhado. Seguindo as técnicas e práticas recomendadas descritas neste artigo, você pode implementar semáforos com eficácia em seus aplicativos Java para garantir um gerenciamento de recursos seguro e eficiente.

Se você tiver alguma dúvida ou quiser compartilhar suas próprias experiências com semáforos, fique à vontade para comentar abaixo!

Leia mais postagens em: Técnicas para gerenciar simultaneidade em Java usando semáforos

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/anh_trntun_4732cf3d299/techniques-for-managing-concurrency-in-java-using-semaphores-5ai?1 Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3