0Pricing
Ruby Academy · Aula

Threads

Execução concorrente.

Threads é uma aula grátis de Ruby Academy no CoddyKit. Esta é a aula 1 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 Ruby Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Ruby Academy inclui 4 aulas no total.

O que é uma linha de execução?

Uma linha de execução é um caminho independente de execução dentro do seu programa. O Ruby permite executar várias linhas de execução para que o trabalho se sobreponha no tempo.

  • O programa principal é executado na linha de execução principal.
  • Você cria mais linhas de execução com Thread.new.
  • As linhas de execução compartilham a mesma memória, portanto podem ler e gravar as mesmas variáveis.

As linhas de execução são ideais quando o seu programa passa tempo esperando (rede, disco, pausas), pois uma linha de execução pode esperar enquanto outra continua trabalhando.

Criando uma linha de execução

Passe um bloco para Thread.new. O bloco será executado em uma nova linha de execução. Chame join para esperar que ela termine antes de o programa sair.

t = Thread.new do
  puts "Hello from the new thread"
end

t.join
puts "Main thread done"

Por que join é importante

Quando a linha de execução principal termina, o Ruby sai e pode não esperar pelas outras linhas de execução. join bloqueia quem o chamou até que a linha de execução-alvo seja concluída.

Sem join, a linha de execução de trabalho talvez nunca tenha a chance de imprimir algo antes de o programa ser encerrado.

t = Thread.new do
  sleep 0.1
  puts "Worker finished"
end

puts "Waiting..."
t.join
puts "All done"

Muitas linhas de execução ao mesmo tempo

Você pode iniciar um grupo de linhas de execução, reuni-las em um vetor e então chamar join para cada uma. Esse é um padrão comum para trabalhos de E/S aproximadamente paralelos.

threads = (1..3).map do |n|
  Thread.new do
    puts "Thread number " + n.to_s
  end
end

threads.each(&:join)
puts "Finished all threads"

Compartilhando variáveis

As linhas de execução compartilham a memória. Uma variável definida antes da linha de execução fica visível dentro dela. Isso é poderoso, mas também perigoso se duas linhas de execução gravarem o mesmo valor.

counter = 0

t = Thread.new do
  counter += 1
end

t.join
puts "Counter is " + counter.to_s

Condições de corrida

Uma condição de corrida acontece quando as linhas de execução intercalam atualizações em dados compartilhados e o resultado depende do momento em que cada operação ocorre.

  • counter += 1 na verdade significa ler, somar e gravar.
  • Duas linhas de execução podem ler o mesmo valor antigo e gravar o mesmo valor novo, fazendo com que um incremento seja perdido.

A solução é coordenar o acesso com um bloqueio.

Mutex: um bloqueio

Um Mutex (exclusão mútua) garante que apenas uma linha de execução execute o código protegido por vez. Envolva a seção crítica em mutex.synchronize.

mutex = Mutex.new
counter = 0

threads = (1..5).map do
  Thread.new do
    mutex.synchronize do
      counter += 1
    end
  end
end

threads.each(&:join)
puts "Counter is " + counter.to_s

Retornando um valor

Thread#value espera que a linha de execução termine e retorna o valor do bloco, como um join automático acompanhado de um resultado.

t = Thread.new do
  2 + 3
end

puts "Result is " + t.value.to_s

Variáveis locais à linha de execução

Cada linha de execução pode armazenar seus próprios valores, identificados por um símbolo, com Thread.current[:key]. Esses valores são privados para essa linha de execução e nunca são compartilhados.

t = Thread.new do
  Thread.current[:name] = "worker"
  puts "Inside: " + Thread.current[:name]
end

t.join

Tratando exceções

Se uma linha de execução lançar um erro, ele permanecerá silencioso até você chamar join ou value, que o lançará novamente. Definir Thread.abort_on_exception = true faz com que os erros encerrem todo o programa imediatamente, o que ajuda na depuração.

t = Thread.new do
  raise "boom"
end

begin
  t.join
rescue => e
  puts "Caught: " + e.message
end

Quando as linhas de execução ajudam

As linhas de execução são excelentes para trabalhos dependentes de E/S, nos quais o tempo é gasto esperando. Elas ajudam menos em trabalhos dependentes da CPU por causa do GVL (abordado a seguir).

  • Bom: baixar muitas URLs e ler muitos arquivos.
  • Limitado: fazer cálculos numéricos intensos em vários núcleos.

Proteja sempre o estado mutável compartilhado com um Mutex.

Verificação rápida

Teste sua compreensão sobre as linhas de execução.

Recapitulação: linhas de execução

Você aprendeu os fundamentos das linhas de execução do Ruby:

  • Thread.new inicia a execução concorrente.
  • join espera; value espera e retorna um resultado.
  • As linhas de execução compartilham a memória, causando condições de corrida.
  • Um Mutex com synchronize protege o estado compartilhado.
  • As linhas de execução são excelentes para trabalhos de E/S.

A seguir, exploraremos por que as linhas de execução não conseguem usar completamente vários núcleos da CPU: o GVL.

Perguntas Frequentes

A aula “Threads” é grátis?

Sim — o texto completo de “Threads” é 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 Ruby Academy, atualize para CoddyKit PRO. O curso de Ruby Academy inclui 4 aulas no total.

O que vou aprender em “Threads”?

Execução concorrente. Você pratica Ruby 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 Ruby Academy?

Nenhuma experiência prévia é necessária. Ruby 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 1 de 4.

Quanto tempo leva a aula “Threads”?

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 Ruby Academy?

Sim. Cada aula de Ruby 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. Threads
  2. O GVL explicado
  3. Fibras
  4. Ractors
← Voltar para Ruby Academy