Sobes.tech
Middle

O que são bloqueios otimistas e pessimistas?

sobes.tech IA

Resposta da IA

Os bloqueios otimistas e pessimistas são abordagens para gerir o acesso paralelo a dados partilhados em ambientes concorrentes (aplicações multithread, bases de dados).

Bloqueio pessimista:

Supõe que os conflitos ao aceder aos dados são prováveis. Antes de aceder a um recurso, o thread ou transação bloqueia-o (de forma exclusiva ou partilhada). Outros threads que tentem aceder a ele esperarão até que o bloqueio seja libertado.

  • Vantagens: Garante a integridade dos dados, é simples de implementar em ambientes com baixa concorrência.
  • Desvantagens: Pode causar bloqueios (esperas), reduzir a capacidade de processamento em alta concorrência (deadlocks).
  • Exemplos: a palavra-chave synchronized em Java, bloqueios ao nível de linhas ou tabelas em bases de dados.
// Exemplo de bloqueio pessimista em Java
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++; // Bloqueio no objeto, apenas um thread pode executar este método de cada vez
    }

    public synchronized int getCount() {
        return count;
    }
}

Bloqueio otimista:

Supõe que os conflitos ao aceder aos dados são pouco prováveis. O acesso aos dados é feito sem bloqueios. Antes de guardar alterações, verifica-se se os dados foram modificados por outro thread desde que foram lidos. Se ocorrerem alterações, a operação é cancelada e geralmente tentada novamente (retry).

  • Vantagens: Alta capacidade de processamento em ambientes com baixa concorrência, sem problemas de deadlocks.
  • Desvantagens: Podem surgir conflitos que requerem reintentos, o que complica a lógica. Não é adequado para operações de longa duração ou com alta probabilidade de conflitos.
  • Exemplos: operações Compare-And-Swap (CAS), gestão de versões em bases de dados (por exemplo, uso de colunas de versão ou marcas de tempo).
// Exemplo de bloqueio otimista usando CAS (java.util.concurrent.atomic)
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        // Tentativa de incrementar de forma atómica
        // Se o valor mudou entre a leitura e a atualização, a tentativa é reexecutada
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

Comparação:

Característica Bloqueio pessimista Bloqueio otimista
Suposição Os conflitos são prováveis Os conflitos são pouco prováveis
Abordagem Bloqueio até ao acesso Acesso sem bloqueio, verificação na escrita
Em ambientes de alta concorrência Pode causar bloqueios, reduzir a capacidade Repetições frequentes, reduzir o desempenho
Em ambientes de baixa concorrência Pode criar sobrecarga Alta capacidade de processamento
Problema de deadlock Possível Impossível (do ponto de vista do acesso concorrente a recursos)