Threads Simples
Threads em Rust funcionam de maneira semelhante às threads em outras linguagens:
use std::thread; use std::time::Duration; fn main() { thread::spawn(|| { for i in 1..10 { println!("Contagem na _thread_: {i}!"); thread::sleep(Duration::from_millis(5)); } }); for i in 1..5 { println!("_Thread_ principal: {i}"); thread::sleep(Duration::from_millis(5)); } }
- Threads são todas “daemon threads”, a thread principal não espera por elas.
- “Panics” em threads são independentes uns dos outros.
- “Panics” podem carregar um payload (carga útil), que pode ser descompactado com
downcast_ref.
- “Panics” podem carregar um payload (carga útil), que pode ser descompactado com
This slide should take about 15 minutes.
-
As APIs de threads do Rust não parecem muito diferentes das de C++.
-
Execute o exemplo.
- O tempo de 5ms é suficientemente folgado para que a thread principal e as threads filhas permaneçam principalmente em sincronia.
- Observe que o programa termina antes que a thread filha alcance 10!
- Isso ocorre porque o main termina o programa e as threads filhas não o mantêm.
- Compare com pthreads/C++ std::thread/boost::thread se desejar.
-
Como esperamos a thread filha terminar?
-
thread::spawnretorna umJoinHandle. Veja a documentação.JoinHandletem um método.join()bloqueante.
-
Use
let handle = thread::spawn(...)e depoishandle.join()para esperar que a thread termine e fazer o programa contar até 10. -
Agora, e se quisermos retornar um valor?
-
Olhe a documentação novamente:
- O encerramento de
thread::spawnretornaT JoinHandle.join()retornathread::Result<T>
- O encerramento de
-
Use o valor de retorno
Resultdehandle.join()para obter acesso ao valor retornado. -
Ok, e quanto ao outro caso?
- Dispare um panic na thread. Observe como isso não afeta
main. - Acessa o payload do panic. Este é um bom momento para falar sobre
Any.
- Dispare um panic na thread. Observe como isso não afeta
-
Agora podemos retornar valores de threads! E quanto a receber entradas?
- Capture algo por referência no encerramento da thread.
- Uma mensagem de erro indica que devemos movê-lo.
- Mova-o, veja que podemos calcular e depois retornar um valor derivado.
-
E se quisermos emprestar?
- O main mata as threads filhas quando retorna, mas outra função apenas retornaria e as deixaria em execução.
- Isso seria acesso após retorno da pilha, o que viola a segurança de memória!
- Como evitamos isso? Veja o próximo slide.