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:
- 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.
- Espera e notificação (Waiting and Notification): O monitor inclui um conjunto de métodos associados
wait(),notify()enotifyAll(). 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. |