0Pricing
Java Academy · Aula

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=full para rastreamentos completos
  • -Djdk.tracePinnedThreads=short para 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 synchronized bloqueante por ReentrantLock
  • Ative jdk.tracePinnedThreads durante os testes
  • Minimize o uso de ThreadLocal; prefira ScopedValue
  • 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 synchronized mantém um portador ocupado; corrija usando ReentrantLock
  • 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

  1. O que são threads virtuais
  2. Criando threads virtuais
  3. Threads de plataforma e virtuais
  4. Armadilhas: fixação e ThreadLocals
← Voltar para Java Academy