Como utilizar ReentrantLock para sincronização de threads?

ReentrantLock é uma alternativa ao synchronized, oferecendo mais controle sobre o bloqueio de threads em Java.

Como utilizar ReentrantLock para sincronização de threads?

O ReentrantLock é uma alternativa ao uso do synchronized em Java, oferecendo maior flexibilidade e controle sobre a sincronização de threads.

1. O que é ReentrantLock?

O ReentrantLock faz parte do pacote java.util.concurrent.locks e permite que uma thread bloqueie e desbloqueie recursos manualmente, garantindo que apenas uma thread por vez acesse um determinado código.

2. Exemplo de uso básico

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Contador {
    private int valor = 0;
    private final Lock lock = new ReentrantLock();

    public void incrementar() {
        lock.lock();
        try {
            valor++;
        } finally {
            lock.unlock();
        }
    }

    public int getValor() {
        return valor;
    }
}

Explicação:

  • lock.lock() bloqueia o acesso ao código para outras threads.
  • finally { lock.unlock(); } garante que o bloqueio seja liberado corretamente.

3. Diferença entre synchronized e ReentrantLock

Característica synchronized ReentrantLock
Liberação automática Sim, quando o método termina Não, deve ser liberado manualmente
Tentativa de bloqueio sem espera Não Sim, com tryLock()
Interrupção de thread bloqueada Não Sim

4. Tentando obter um bloqueio sem esperar

Podemos usar tryLock() para tentar adquirir o bloqueio sem aguardar indefinidamente:

if (lock.tryLock()) {
    try {
        // Código protegido pelo bloqueio
    } finally {
        lock.unlock();
    }
} else {
    System.out.println("Outra thread já está executando esta operação.");
}

5. Fazendo bloqueios com tempo limite

Para evitar deadlocks, podemos definir um tempo máximo para aguardar o bloqueio:

try {
    if (lock.tryLock(2, TimeUnit.SECONDS)) {
        try {
            // Código crítico
        } finally {
            lock.unlock();
        }
    } else {
        System.out.println("Não foi possível obter o bloqueio dentro do tempo limite.");
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

Conclusão

O ReentrantLock oferece mais controle sobre a sincronização de threads do que synchronized, sendo útil em situações onde é necessário tempo de espera limitado, interrupção de threads bloqueadas ou tentativa de bloqueio sem espera.

Em sistemas multithread, a escolha entre synchronized e ReentrantLock pode impactar diretamente o desempenho da aplicação. O synchronized é mais simples e confiável para bloqueios básicos, enquanto o ReentrantLock permite um controle refinado, evitando situações como deadlocks e esperas indefinidas.

Algumas aplicações:

  • Evitar race conditions em sistemas concorrentes
  • Garantir exclusão mútua ao acessar recursos compartilhados
  • Gerenciar melhor o tempo de espera de threads bloqueadas
  • Evitar deadlocks em sistemas complexos

Dicas para quem está começando

  • Sempre chame lock.unlock() dentro de um finally
  • Use tryLock() para evitar esperas indefinidas
  • Evite bloquear recursos por mais tempo do que o necessário
  • Prefira synchronized para casos simples e ReentrantLock para maior controle

Contribuições de Rodrigo Farias

Compartilhe este tutorial: Como utilizar ReentrantLock para sincronização de threads

Compartilhe este tutorial

Continue aprendendo:

O que é synchronized e como utilizá-lo

A palavra-chave synchronized em Java permite controlar o acesso de múltiplas threads a um recurso compartilhado, evitando Race Conditions.

Tutorial anterior

O que são Semaphore e CountDownLatch

Semaphore e CountDownLatch são mecanismos de sincronização que ajudam a controlar o acesso de múltiplas threads a recursos compartilhados.

Próximo tutorial