Goroutines não são threads!

Mas são parecidas.

Gabriel Albuquerque (Albuca)
4 min readMar 20, 2023
Imagem de fundo por: Bozhin Karaivanov

Contextualizando

Entendo que muitas pessoas (assim como eu), ao conhecer o conceito de Goroutines pensou “pera, isso aí são threads”, mas apesar de ser parecidos, tanto as threads quanto as goroutines têm suas peculiaridades e propósitos que temos que levar em consideração quando vamos trabalhar com elas.

Threads

“Thread” é o nome que damos para uma pequena peça de um processo que que está sendo executado, em outras palavras, a thread é a menor unidade lógica que executa o código do nosso programa.

Arquitetura dos processos:

Basicamente, nosso sistema operacional roda aplicações, essas aplicações quando são carregadas na memória para execução, são divididas em um ou mais processos.

Sempre bom esclarecer que quando falamos de processos, estamos falando de um conceito organizacional, dentro de um processo temos pelo menos uma thread e quando a CPU “executa” o processo, na verdade, está executando a(s) thread(s) desse processo.

A execução das threads

Como podemos ver, um processo pode ter mais de uma thread, quando temos múltiplas threads elas podem ser executadas das seguintes maneiras:

1 — Maneira procedural, ou seja, ao finalizar a execução de uma, partir para a próxima.
2 — Maneira concorrente, basicamente organizar as threads por prioridade e ir executando de acordo (não é necessário aguardar uma thread finalizar para começar a próxima).
3 — Maneira paralela: duas ou mais threads sendo executadas ao mesmo tempo (possível com processadores Multi-Threading).

O responsável por definir qual thread será executada e também por gerenciar a “troca de contextos” na troca de execução entre uma e outra, é um cara chamado “scheduler” que roda no Kernel. O scheduler gerencia as threads a nível global no sistema, ou seja, ele é responsável por cuidar das threads de todos os processos de todas as aplicações que estão rodando.

Por ter que dividir o scheduler com outras threads do sistema, a troca de contextos acaba se tornando um pouco lenta e custosa quando queremos trabalhar com processos multi-threading, isso não é um problema muito grave tendo em consideração que funciona muito bem a nível de S.O (para qual foi projetado).

Goroutines

Goroutines são funções ou métodos do código Go que rodam de forma concorrente durante a execução do programa.

Muitos pensam que ao criar uma goroutine, estamos criando uma thread, mas na verdade não, as goroutines são muito menores e mais dinâmicas do que as threads e têm um propósito diferente das mesmas.

Além de serem muito menores, quando temos nossa aplicação em Go rodando, o que vai gerenciar as nossas goroutines é o próprio scheduler do Go (e não o do Kernel), esse scheduler tem a tarefa de alocar múltiplas Goroutines para N threads, essa técnica de schedule é chamada de NM Scheduling.

A maior vantagem de ter o próprio scheduler, é que as goroutines não ficam dependentes do scheduler do Kernel que precisa se preocupar com tudo o que está acontecendo na máquina, quando o Go precisa trocar de uma goroutine para outra, o processo se torna mais rápido pois temos um scheduler que foi projetado para trabalhar com várias goroutines e não com threads a nível global.

Além disso, quando o scheduler do Go realiza o NM Scheduling ele é capaz de alocar mais de uma goroutine para uma thread, o que vai tornar a troca de contextos/goroutine ainda mais rápida, pois não vai precisar realizar todo o tratamento de estado que é realizado quando vamos trocar de uma thread para outra, o que repetindo, é um processo projetado para funcionar a nível de sistema.

Tanto as goroutines quanto o scheduler do Go foram pensados para rodar a nível de aplicação e não de sistema, por isso são mais leves, dinâmicos e mais rápidos para funcionar, estão dentro de seu próprio contexto.

Referências

--

--

No responses yet