Armadilhas: fixação e ThreadLocals
Evite bloquear threads portadoras.
Armadilhas: fixação e ThreadLocals é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
O que pode dar errado
Os encadeamentos virtuais são poderosos, mas duas armadilhas podem prejudicar silenciosamente sua escalabilidade: fixação e uso excessivo de ThreadLocals.
Esta lição explica ambas e mostra como evitá-las.
O que é fixação
Fixação ocorre quando um encadeamento virtual não consegue se desmontar do portador enquanto está bloqueado. O encadeamento do sistema operacional que serve como portador permanece preso, anulando o benefício de escalabilidade.
Quando muitos portadores ficam fixados, a vazão entra em colapso.
Causa: bloqueio sincronizado
A causa clássica é bloquear dentro de um bloco ou método synchronized. Ao manter o monitor e depois bloquear, o encadeamento virtual permanece fixado ao portador.
Observação: no JDK 24 ou posterior, essa limitação foi em grande parte removida, mas no Java 21 ela é uma preocupação real.
Exemplo de fixação a evitar
Este padrão pode causar fixação no Java 21: bloquear enquanto mantém um monitor. Ele ainda funciona corretamente, mas não é escalável.
public class Main {
static final Object lock = new Object();
static void risky() {
synchronized (lock) {
try { Thread.sleep(10); } catch (InterruptedException e) {}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().start(Main::risky);
t.join();
System.out.println("Done (but this blocked inside synchronized)");
}
}A correção: ReentrantLock
Substitua synchronized por ReentrantLock quando a seção crítica puder bloquear. As interfaces de bloqueio são compatíveis com encadeamentos virtuais e permitem a desmontagem.
import java.util.concurrent.locks.ReentrantLock;
public class Main {
static final ReentrantLock lock = new ReentrantLock();
static void safe() {
lock.lock();
try {
try { Thread.sleep(10); } catch (InterruptedException e) {}
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().start(Main::safe);
t.join();
System.out.println("Done without pinning");
}
}Diagnosticando a fixação
Você pode solicitar à JVM que imprima um rastreamento de pilha sempre que ocorrer uma fixação, iniciando com:
-Djdk.tracePinnedThreads=fullpara rastreamentos completos-Djdk.tracePinnedThreads=shortpara linhas únicas
Isso ajuda a localizar as seções synchronized problemáticas.
ThreadLocals ficam caros
ThreadLocal armazena o estado de cada encadeamento. Com alguns encadeamentos de plataforma, isso não é um problema. Com milhões de encadeamentos virtuais, cada um carregando sua própria cópia, o consumo de memória dispara.
Audite suas bibliotecas: armazenamento em cache, formatação e objetos de contexto frequentemente ocultam ThreadLocals.
ThreadLocal continua funcionando
ThreadLocal não é proibido; apenas use-o com moderação. Cada encadeamento virtual recebe seu próprio valor, como esperado.
public class Main {
static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().start(() -> {
CONTEXT.set("request-42");
System.out.println("Context: " + CONTEXT.get());
CONTEXT.remove();
});
t.join();
}
}Prefira ScopedValue
Java introduziu ScopedValue como uma alternativa mais leve para compartilhar dados imutáveis com um tempo de vida limitado. Ele evita o custo do armazenamento mutável por encadeamento de ThreadLocal e se ajusta ao modelo de concorrência estruturada.
Quando você só precisa transmitir um contexto somente leitura por uma cadeia de chamadas, prefira essa opção.
Não use agrupamento
Outra armadilha sutil é tratar os encadeamentos virtuais como um recurso escasso e agrupá-los. Isso reintroduz contenção e vazamento de ThreadLocal entre as tarefas.
Sempre crie um encadeamento virtual por tarefa e deixe-o terminar.
Lista de verificação para escalabilidade
Antes de colocar encadeamentos virtuais em produção:
- Substitua
synchronizedbloqueante porReentrantLock - Ative
jdk.tracePinnedThreadsdurante os testes - Minimize o uso de
ThreadLocal; prefiraScopedValue - Nunca agrupe encadeamentos virtuais
Verificação rápida
Identifique a substituição segura para um bloco synchronized bloqueante.
Recapitulação
Você aprendeu as principais armadilhas:
- Fixação: bloquear dentro de
synchronizedmantém um portador ocupado; corrija usandoReentrantLock - Faça o diagnóstico com
-Djdk.tracePinnedThreads - O custo de ThreadLocal aumenta com a quantidade de encadeamentos; prefira
ScopedValue - Nunca agrupe encadeamentos virtuais
Isso conclui o curso de encadeamentos virtuais.
Perguntas Frequentes
A aula “Armadilhas: fixação e ThreadLocals” é grátis?
Sim — o texto completo de “Armadilhas: fixação e ThreadLocals” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Armadilhas: fixação e ThreadLocals”?
Evite bloquear threads portadoras. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Armadilhas: fixação e ThreadLocals”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- O que são threads virtuais
- Criando threads virtuais
- Threads de plataforma e virtuais
- Armadilhas: fixação e ThreadLocals