Sobes.tech
Middle+

Como funciona o mecanismo de sincronização 'synchronized' na linguagem Java por baixo dos panos?

sobes.tech IA

Resposta da IA

O mecanismo synchronized em Java baseia-se no conceito de monitores (objetos monitor). A cada objeto em Java está associado um monitor.

Quando um thread entra num bloco ou método sincronizado, tenta adquirir o monitor do objeto correspondente. Se o monitor estiver livre, o thread adquire-o e continua a execução. Se o monitor estiver ocupado por outro thread, o thread atual fica bloqueado e passa a um estado de espera até que o monitor seja libertado.

Quando um thread sai de um bloco ou método sincronizado (quer termine com sucesso ou lance uma exceção), ele liberta o monitor.

Dentro do monitor, são implementados:

  1. Exclusão mútua (Mutual Exclusion): Apenas um thread pode possuir o monitor de um objeto de cada vez. Isto garante que apenas um thread pode executar código sincronizado para esse objeto.
  2. Espera e notificação (Waiting and Notification): O monitor inclui um conjunto de métodos associados wait(), notify() e notifyAll(). Estes métodos permitem aos threads que possuem o monitor libertá-lo temporariamente e passar a um estado de espera, sendo posteriormente notificados por outros threads sobre a possibilidade de continuar.

A implementação a baixo nível inclui:

  • Instrução monitorenter: Executada ao entrar num bloco ou método sincronizado. Tenta adquirir o monitor do objeto.
  • Instrução monitorexit: Executada ao sair de um bloco ou método sincronizado (quer seja por término normal ou por exceção). Liberta o monitor do objeto.

Estas instruções fazem parte do código byte de Java e são geridas pela máquina virtual Java (JVM). A JVM utiliza mecanismos nativos do sistema operativo (como mutexes, semáforos) para gerir os monitores e o bloqueio/desbloqueio de threads.

A aquisição do monitor pode ser implementada ao nível do objeto (para métodos e blocos de instância) ou ao nível da classe (para métodos e blocos estáticos), usando o objeto Class como bloqueio.

Exemplo de uso:

public class Counter {
    private int count = 0;

    public synchronized void increment() { // Método sincronizado
        count++;
    }

    public void decrement() {
        synchronized (this) { // Bloco sincronizado
            count--;
        }
    }

    public static synchronized void staticMethod() { // Método estático sincronizado
        // ...
    }
}

Tabela de métodos da classe Object relacionados com monitores:

Método Descrição
wait() O thread que possui o monitor liberta-o temporariamente e passa a aguardar.
notify() Notifica um dos threads em espera que pode tentar adquirir o monitor e continuar.
notifyAll() Notifica todos os threads em espera.