> For the complete documentation index, see [llms.txt](https://concorrencia101.leandronsp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://concorrencia101.leandronsp.com/parte-ii-concorrencia-em-diferentes-linguagens/concorrencia-em-c/green-threads.md).

# Green threads

Quando falamos de **threads**, geralmente estamos nos referindo a *threads do sistema operacional*, ou **kernel threads**. Algumas implementações de linguagens de programação, como o *GCC em C*, permitem utilizar kernel threads, que no caso do C é através da função `pthread_create` .

Mas como vimos no tópico sobre os desafios com o uso de kernel threads, a gestão de milhares de threads pode aumentar consideravelmente a latência do sistema.

Como alternativa, algumas implementações optam por usar abstrações similar a threads dentro do próprio runtime, pelo que precisam desenvolver o próprio escalonador de threads.&#x20;

A essas threads que vivem dentro do runtime, ou como costumamos dizer, *a nível do usuário*, damos o nome de **green threads**.

Mas antes de falarmos das green threads, vamos relembrar o funcionamento de uma kernel thread.

## Funcionamento de uma kernel thread

Como já aprendemos nos tópicos anteriores, em C conseguimos criar threads do sistema operacional, ou kernel threads. Basicamente, uma kernel thread tem uma pilha onde guarda o estado de execução entre outros metadados:

<figure><img src="https://1347906346-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FADWkcUWoXJQdqxwxxE7z%2Fuploads%2FuLwwDNFbTNkP31m07C5d%2FScreenshot%202024-12-29%20at%2000.42.26.png?alt=media&amp;token=4e1a333c-6eef-4da0-b43a-096ca65bf8e5" alt="" width="563"><figcaption></figcaption></figure>

Em C, a chamada da função `pthread_create` basicamente cria uma kernel thread, então a gestão de escalonamento e troca de contexto fica completamente a cargo do kernel (SO), e não do GCC:

<figure><img src="https://1347906346-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FADWkcUWoXJQdqxwxxE7z%2Fuploads%2FhA5IABLOMk3KNMqXcpWA%2FScreenshot%202024-12-29%20at%2000.55.18.png?alt=media&amp;token=d99237e7-69f2-49d3-b6cb-1787f44bc7dd" alt="" width="563"><figcaption></figcaption></figure>

## Como funciona uma green thread

Uma green thread geralmente tem uma estrutura similar a uma kernel thread, contendo sua própria pilha de memória mas compartilhando a memória principal do processo.&#x20;

Mas uma green thread tem a vantagem de não levar com a latência da criação de kernel threads, ou seja, dependendo da *implementação de green threads no runtime*, podemos criar milhares, senão **milhões de green threads** mantendo baixa latência.

A nível de implementação, em determinado momento vamos precisar "associar" as green threads às kernel threads, afinal:

> Todo programa roda em uma thread principal, ou seja, para o escalonador do sistema operacional é *tudo thread*, ou melhor ainda, **é tudo task**

O desafio é então *multiplexar* um número arbitrário de green threads para kernel threads, e isto pode ser feito de várias formas. Vamos a seguir detalhar alguns tipos comuns de implementação de green threads.

### 1. Uma kernel thread, múltiplas green threads

Neste tipo de implementação, temos apenas uma thread principal do programa que é mapeada diretamente para uma kernel thread. E dentro desta thread, criamos múltiplas green threads:

<figure><img src="https://1347906346-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FADWkcUWoXJQdqxwxxE7z%2Fuploads%2F918cdL1BOcDMmFe7rO7f%2FScreenshot%202024-12-29%20at%2001.14.21.png?alt=media&amp;token=1d46fdac-dcb0-4096-a822-d189ceb062e4" alt="" width="563"><figcaption></figcaption></figure>

A vantagem desta abordagem é que temos **menos latência** comparando com o uso indiscriminado de kernel threads, mas por outro lado, a desvantagem é que **não temos um paralelismo real** mesmo em CPU multi-core, pois o sistema operacional não sabe que se trata de uma green thread, então no fim das contas é apenas **uma thread** sendo utilizada na CPU.

### 2. Multiplexação de N green threads para M kernel threads

Esta abordagem é muito comum no runtime Go, e é basicamente a capacidade de criar uma kernel thread para um conjunto específico de green threads:

<figure><img src="https://1347906346-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FADWkcUWoXJQdqxwxxE7z%2Fuploads%2FMV27yCka2EiaFparkO8Y%2FScreenshot%202024-12-29%20at%2001.15.20.png?alt=media&amp;token=caec9821-e33a-4026-8e78-dc279e4e07a9" alt="" width="563"><figcaption></figcaption></figure>

A vantagem nisso é que podemos utilizar mais paralelismo, uma vez que cada kernel thread pode utilizar um núcleo de CPU. Se o runtime for espertinho o suficiente, temos uma situação muito interessante para lidar com concorrência e paralelismo.

> Alô Gophers, o momento de vocês está chegando :P

### 3. Múltiplos escalonadores

Outra abordagem muito interessante, e que é utilizada na implementação do Erlang/Elixir (BEAM), é que poderíamos multiplexar kernel threads pra cada escalonador. Assim, cada escalonador iria cuidar de um número X de *green threads* mantendo o paralelismo real.

<figure><img src="https://1347906346-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FADWkcUWoXJQdqxwxxE7z%2Fuploads%2FYGB0gpdKJRswW2JQDdJy%2FScreenshot%202024-12-29%20at%2001.22.42.png?alt=media&amp;token=559a030e-0235-4a8b-978a-81a3ab4c58ad" alt=""><figcaption></figcaption></figure>

Mas a ideia por enquanto não é falar de Go nem Erlang, pois estamos ainda no C. Chegou o momento de entender como podemos trabalhar com green threads em C.

## Green threads em C

Infelizmente, a implementação padrão do GCC não traz suporte a green threads. O que até faz sentido, imagina o C trazer isso? Seria overkill, sendo uma linguagem bastante genérica, de propósito geral e muito perto do sistema operacional.

Mas há algumas bibliotecas externas que trazem este conceito, onde podemos ter "green threads" em C contando com uma estrutura de escalonamento das threads:

* [libdill.org](https://libdill.org/): green threads (chamadas na lib de **corrotinas**), com comunicação baseada em canais e escalonamento cooperativo
* [libmill.org](https://libmill.org/): similar à libdill, mas implementada de forma mais robusta e escalável, com multiplexing de kernel threads semelhante ao que temos em Go
* ...entre outras, como libtask, libcoro, GNU pth etc
