Utilização Básica do synchronized
O synchronized é uma palavra-chave em Java para sincronização de threads, com três formas de aplicação:
Método de Instância Sinrconizado
public synchronized void executar() {
// Código sincronizado
}
Bloqueia a instância atual (this). O objeto invocador torna-se o bloqueio.
Método Estático Sincronizado
public static synchronized void processar() {
// Código sincronizado
}
Bloqueia o objeto Class correspondente, único em nível de JVM.
Bloco Sincronizado
public void operacao() {
synchronized(recurso) {
// Código sincronizado
}
}
Permite especificar qualquer objeto como bloqueio (recurso).
Princípios Fundamentais
Representação em Bytecode
Métodos sincronizados possuem o flag ACC_SYNCHRONIZED. Blocos usam instruções:
monitorenter
// Código
monitorexit
Mecanismo de Monitor
Cada objeto possui um monitor com estrutura:
| Componente | Função |
|---|---|
| Contador (_count) | Registra reentrâncias |
| Proprietário (_owner) | Thread detentora do bloqueio |
| Conjunto de Espera (_WaitSet) | Threads em wait() |
| Fila de Entrada (_EntryList) | Threads bloqueadas aguardando acesso |
Ciclo de Vida do Bloqueio
- Thread executa
monitorenter - Contador=0: Obtém bloqueio, contador=1, define proprietário
- Contador>0: Incrementa contador (reentrância)
- Bloqueio ocupado: Thread entra em
_EntryList monitorexitdecrementa contador- Contador=0: Libera bloqeuio e notifica threads em espera
Semântica de Memória
- Entrada no bloco: Invalida cache local, lê variáveis da memória principal
- Saída do bloco: Atualiza memória principle com modificações locais
Otimizações da JVM
Evolução de Bloqueio
- Sem bloqueio: Estado inicial
- Bloqueio tendencioso: Para acesso exclusivo (registra ID da thread)
- Bloqueio leve: Para execução alternada (usando CAS)
- Bloqueio pesado: Para alta contenção (mutex do SO)
Consolidação de Bloqueios
// Original
public void metodo() {
synchronized (this) { tarefaA(); }
synchronized (this) { tarefaB(); }
}
// Otimizado
public void metodo() {
synchronized (this) {
tarefaA();
tarefaB();
}
}
Eliminação de Bloqueios
// Original (bloqueio redundante)
public void processar() {
Objeto temp = new Objeto();
synchronized(temp) { executar(); }
}
// Otimizado
public void processar() {
executar();
}