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_sCondiçõ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 += 1na 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_sRetornando 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_sVariá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.joinTratando 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
endQuando 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.newinicia a execução concorrente.joinespera;valueespera e retorna um resultado.- As linhas de execução compartilham a memória, causando condições de corrida.
- Um
Mutexcomsynchronizeprotege 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
- Threads
- O GVL explicado
- Fibras
- Ractors