Agora que entendemos como funciona o forking de processos, vamos explorar as threads. Threads são uma forma mais leve de concorrência, permitindo que múltiplas tarefas sejam executadas dentro do mesmo processo, compartilhando o mesmo espaço de memória.
Conforme explicado no módulo de C, conseguimos criar POSIX Threads através da chamada de função pthread_create. Na linguagem Ruby, conseguimos manipular kernel threadsatravés da classe Thread.
# Função que será executada pela threaddefhandleputs"Hello from thread!"end# Cria uma threadthread = Thread.newdo handleendputs"Hello from main thread!"# Aguarda a thread terminarthread.join
Hello from main thread!
Hello from thread!
Simples, não? Podíamos também passar qualquer código Ruby pra dentro do bloco da thread, não precisa ser necessariamente um método:
# Cria uma threadthread = Thread.newdoputs"Hello from thread!"endputs"Hello from main thread!"# Aguarda a thread terminarthread.join
Um exemplo mais robusto
Agora vamos fazer um exemplo mais complexo com threads, assim como fizemos com forking de processos:
defhandle(thread_id)puts"Thread #{thread_id} is running..."sleep(2) # Simula uma tarefa que leva 2 segundosputs"Thread #{thread_id} is finished."endthreads = []# Criação das threads3.timesdo|i| threads <<Thread.new(i +1) do|thread_id|handle(thread_id)# Passa o ID da thread como argumentoendend# Aguarda todas as threads finalizaremthreads.each_with_indexdo|thread, i| thread.joinputs"Thread #{i +1} has been finished."endputs"All threads are finished."
Thread 1 is running...
Thread 2 is running...
Thread 3 is running...
Thread 1 is finished.
Thread 3 is finished.
Thread 2 is finished.
Thread 1 has been finished.
Thread 2 has been finished.
Thread 3 has been finished.
All threads are finished.
Ruby dispensa comentários, não?
Vamos agora ver como Ruby resolve problemas de race condition.