"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Explorando a fixação no mecanismo de thread virtual da JVM

Explorando a fixação no mecanismo de thread virtual da JVM

Publicado em 2024-11-08
Navegar:743

Os threads virtuais do Java oferecem uma alternativa leve aos threads de sistema operacional tradicionais, permitindo um gerenciamento eficiente de simultaneidade. Mas compreender o seu comportamento é crucial para um desempenho ideal. Esta postagem do blog se aprofunda na fixação, um cenário que pode impactar a execução de threads virtuais, e explora técnicas para monitorar e resolver isso.

Threads virtuais: uma abordagem de simultaneidade leve

Os threads virtuais do Java são entidades gerenciadas que são executadas sobre os threads subjacentes do sistema operacional (threads de transporte). Eles fornecem uma maneira mais eficiente de lidar com a simultaneidade em comparação com a criação de vários threads de sistema operacional, pois geram menor sobrecarga. A JVM mapeia threads virtuais para threads transportadoras dinamicamente, permitindo uma melhor utilização de recursos.

  • Gerenciados pela JVM: Ao contrário dos threads do sistema operacional que são gerenciados diretamente pelo sistema operacional, os threads virtuais são criados e agendados pela Java Virtual Machine (JVM). Isso permite controle e otimização mais refinados no ambiente JVM.

  • Sobrecarga reduzida: criar e gerenciar threads virtuais incorre em sobrecarga significativamente menor em comparação com threads do sistema operacional. Isso ocorre porque a JVM pode gerenciar um conjunto maior de threads virtuais de forma eficiente, utilizando um número menor de threads de sistema operacional subjacentes.

  • Compatibilidade com código existente: Threads virtuais são projetados para serem perfeitamente integrados ao código Java existente. Eles podem ser usados ​​junto com threads de sistema operacional tradicionais e trabalhar dentro de construções familiares como Executor e ExecutorService para gerenciamento simultâneo.

A figura abaixo mostra a relação entre threads virtuais e threads de plataforma:

Exploring Pinning in JVM


Fixação: quando um thread virtual fica preso

A fixação ocorre quando um thread virtual fica vinculado ao seu thread transportador. Basicamente, isso significa que o thread virtual não pode ser preemptado (alternado para outro thread de transporte) enquanto estiver em um estado fixado. Aqui estão cenários comuns que acionam a fixação:

  • Blocos e métodos sincronizados: a execução de código dentro de um bloco ou método sincronizado leva à fixação. Isso garante acesso exclusivo a recursos compartilhados, evitando problemas de corrupção de dados.

Exemplo de código:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

  public static void main(String[] args) throws InterruptedException {

    final Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



Neste exemplo, quando um thread virtual entra no bloco sincronizado, ele fica preso ao seu thread transportador, mas isso nem sempre é verdade. A palavra-chave sincronizada do Java por si só não é suficiente para causar fixação de thread em threads virtuais. Para que a fixação de thread ocorra, deve haver um ponto de bloqueio dentro de um bloco sincronizado que faça com que um thread virtual acione o estacionamento e, em última análise, não permita a desmontagem de seu thread transportador. A fixação de threads pode causar uma diminuição no desempenho, pois anularia os benefícios do uso de threads leves/virtuais.

Sempre que um thread virtual encontra um ponto de bloqueio, seu estado é transferido para PARKING. Esta transição de estado é indicada invocando o método VirtualThread.park():

// JDK core code
void park() {
  assert Thread.currentThread() == this;
  // complete immediately if parking permit available or interrupted
  if (getAndSetParkPermit(false) || interrupted)
    return;
  // park the thread
  setState(PARKING);
  try {
    if (!yieldContinuation()) {
      // park on the carrier thread when pinned
      parkOnCarrierThread(false, 0);
    }
  } finally {
    assert (Thread.currentThread() == this) && (state() == RUNNING);
  }
}

Vamos dar uma olhada em um exemplo de código para ilustrar esse conceito:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

  public static void main(String[] args) {

    Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



  • Métodos nativos/funções estrangeiras: a execução de métodos nativos ou funções estrangeiras também pode causar fixação. A JVM pode não ser capaz de gerenciar com eficiência o estado do thread virtual durante essas operações.

Monitorando a fixação com -Djdk.tracePinnedThreads=full

O sinalizador -Djdk.tracePinnedThreads=full é um argumento de inicialização da JVM que fornece informações de rastreamento detalhadas sobre a fixação de thread virtual. Quando ativado, ele registra eventos como:

  • ID do tópico virtual envolvido na fixação
  • ID do encadeamento da operadora ao qual o encadeamento virtual está fixado
  • Traço de pilha indicando a seção de código que está causando a fixação

Use esse sinalizador criteriosamente apenas durante sessões de depuração, pois ele introduz sobrecarga de desempenho.

  1. Compile nosso código de demonstração:

    javac Main.java
    
  2. Inicie o código compilado com o sinalizador -Djdk.tracePinnedThreads=full:

    java -Djdk.tracePinnedThreads=full Main
    
  3. Observe a saída no console, que mostra informações detalhadas sobre a fixação de thread virtual:

    Thread[#29,ForkJoinPool-1-worker-1,5,CarrierThreads]
    java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:183)
    java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
    java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:621)
    java.base/java.lang.VirtualThread.sleepNanos(VirtualThread.java:791)
    java.base/java.lang.Thread.sleep(Thread.java:507)
    Counter.increment(Main.java:38) 
    
    

Consertando fixação com bloqueios reentrantes

A fixação é um cenário indesejável que impede o desempenho de threads virtuais. As travas reentrantes servem como uma ferramenta eficaz para neutralizar a fixação. Veja como você pode usar bloqueios reentrantes para mitigar situações de fixação:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

public class Main {

  public static void main(String[] args) {

    Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



No exemplo atualizado, usamos um ReentrantLock em vez de um bloco sincronizado. O thread pode adquirir o bloqueio e liberá-lo imediatamente após concluir sua operação, reduzindo potencialmente a duração da fixação em comparação com um bloco sincronizado que pode reter o bloqueio por um período mais longo.

Para concluir

Os threads virtuais do Java são um testemunho da evolução e das capacidades da linguagem. Eles oferecem uma alternativa nova e leve aos threads de sistema operacional tradicionais, fornecendo uma ponte para o gerenciamento eficiente de simultaneidade. Reservar um tempo para se aprofundar e compreender conceitos-chave, como fixação de threads, pode equipar os desenvolvedores com o conhecimento para aproveitar todo o potencial desses threads leves. Esse conhecimento não apenas prepara os desenvolvedores para aproveitar os recursos futuros, mas também os capacita a resolver problemas complexos de controle de simultaneidade de maneira mais eficaz em seus projetos atuais.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/yanev/exploring-pinning-in-jvms-virtual-thread-mechanism-5h13?1 Se houver alguma violação, entre em contato com [email protected] para excluí-la
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3