> 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/definindo-ambientes-de-execucao.md).

# Definindo ambientes de execução

Antes de falarmos das diferenças entre algumas *implementações* de **linguagens de programação**, precisamos **definir** o que é uma linguagem de programação.\
\
De acordo com a Wikipedia:

> A linguagem de programação é um método padronizado, formado por um conjunto de [regras sintáticas](https://pt.wikipedia.org/wiki/Sintaxe) e semânticas, de implementação de um [código fonte](https://pt.wikipedia.org/wiki/C%C3%B3digo_fonte) - que pode ser [compilado](https://pt.wikipedia.org/wiki/Compilador) e transformado em um [programa de computador](https://pt.wikipedia.org/wiki/Programa_de_computador), ou usado como [script](https://pt.wikipedia.org/wiki/Linguagem_de_script) [interpretado](https://pt.wikipedia.org/wiki/Linguagem_interpretada) - que informará [instruções](https://pt.wikipedia.org/wiki/C%C3%B3digo_de_m%C3%A1quina) de processamento ao [computador](https://pt.wikipedia.org/wiki/Computador).

Ou seja, quando falamos em **linguagem de programação**, estamos nos referindo a uma especificação sintática e semântica que, através de um processo de **compilação** (ou interpretação), será transformado em código de máquina que o computador possa entender.

Para que uma linguagem seja executada no computador, é preciso ser implementada através de um programa, ou conjunto de programas e ferramentas, formando um "ambiente", onde será feito o processo de compilação, interpretação e/ou execução. Estas instruções irão utilizar **recursos do sistema operacional** que, por sua vez, irá manipular recursos de hardware, como CPU, memória e I/O.

<figure><img src="/files/hubTNMQkeAPpNWAICASq" alt="" width="563"><figcaption></figcaption></figure>

> Com isso conseguimos entender porque é tão importante a primeira parte deste guia, amém?

## Compiladores

Compilador é um programa que, dado um input que é código-fonte que segue a especificação de uma linguagem, aplica transformações e gera um executável que contém código de máquina da arquitetura do computador ou um código intermediário.

Exemplos de linguagens que utilizam compiladores: C (GCC, Clang),  Java (javac), Kotlin (kotlinc), Go (gc), Rust (rustc)&#x20;

<figure><img src="/files/LHC2SIvMstrhmvZEVAFz" alt="" width="563"><figcaption></figcaption></figure>

É possível haver mais de uma implementação para cada linguagem de programação. Vai depender da adesão, investimentos feitos entre outros aspectos.

## Interpretadores

Interpretador é um programa que, dado um input que é código-fonte que segue a especificação de uma linguagem, aplica transformações e executa as instruções da arquitetura "em tempo real".

Exemplos de linguagens que utilizam interpretadores: Python (CPython), Ruby (CRuby), PHP (Zend), Javascript (V8), Java (JVM)

Assim como no caso dos compiladores, é possível haver mais de uma implementação de interpretador para cada linguagem:

<figure><img src="/files/vY9vPM7Ci7spWToSoDtG" alt="" width="563"><figcaption></figcaption></figure>

Repare na principal diferença entre interpretador e compilador: o compilador gera um executável, enquanto que o interpretador vai traduzindo e executando diretamente. Há vantagens e desvantagens em ambos os casos, inclusive há diversos ambientes que fazem um misto de processo de compilação com um interpretador embutido.

## Vai um Javinha aí?

Por exemplo, em Java, o compilador `javac` não gera um código de máquina da arquitetura diretamente, mas sim um "bytecode" intermediário. Então, o bytecode é executado por um interpretador que vem dentro do ambiente Java. A este ambiente de execução (*runtime*), que é capaz de interpretar os bytecodes gerados pelo `javac`e traduzir para instruções da arquitetura do computador, chamamos de *Java Virtual Machine*, ou simplesmente **JVM**.

<figure><img src="/files/G6790aZhoDMQ5qIswvNO" alt=""><figcaption></figcaption></figure>

## E por quê precisamos saber disto com relação a concorrência?

Como vimos na primeira parte do guia, o sistema operacional oferece recursos (chamadas de sistema,  **syscalls**) para criar processos, threads e gerenciar recursos de I/O:

* criação de processos e threads por meio da syscall **clone**
* gerenciar recursos de I/O utilizando as syscalls **read**, **write**, **open** etc
* gerenciar recursos de I/O assíncrono com as syscalls **select**, **epoll**, **io\_uring** etc

Ou seja, as implementações de linguagens de alto nível precisariam fazer estas chamadas. E, pra nossa sorte, praticamente **todas as linguagens mainstream** (de propósito geral) fornecem formas de fazer estas chamadas ao sistema operacional.

> Seria muito estranho uma linguagem não permitir a chamada de syscalls, né? Pra quê serviria esta linguagem então, se não fosse pra chamar syscalls no SO com o intuito de manipular recursos de hardware?

## Ambientes de execução (runtimes)

Algumas implementações acabam por ter um conjuto de compilador com interpretador, como vimos no exemplo do Java. E não só, podem também trazer técnicas de alto nível para criação de "user threads" (que são threads que vivem apenas dentro do ambiente, e não threads do SO), garantindo a troca de contexto entre elas e sua execução, tudo dentro do ambiente.

Geralmente, estes ambientes se chamam **runtimes**. Poderíamos tecnicamente chamar tudo de runtime, mas em alguns casos isto não é precisamente correto, como no caso do GCC, que é apenas um conjunto de ferramentas para compilação de código C.

Entretanto, podemos acordar, neste guia, que iremos tratar tudo por "runtime" (ambientes de execução), não importa se é apenas um compilador, um interpretador, um híbrido, se implementa user threads  ou não, enfim. Vou chamar tudo de *runtime* simplesmente.

> Me perdoem, acadêmicos de plantão. Não é hoje que vocês vão me cancelar

Aqui vai uma lista das principais implementações de algumas linguagens que vamos abordar ao longo deste guia:

* C (GCC)
* Java JDK (javac + JVM)
* Python (CPython)
* Ruby (CRuby, ou MRI)
* Javascript (V8, usado no Chrome e também no Node.js)
* PHP (Zend)
* Go (gc)
* Rust (rustc)
* Kotlin (kotlinc + JVM)
* Elixir (BEAM)

Acho que com estas linguagens dá pra cobrir diversas funcionalidades de concorrência. Iremos entender as principais diferenças, casos de uso e suas vantagens/desvantagens. Vamos fazer uma viagem longa através dos processos, criação de threads no SO, criação de threads dentro do runtime, manipulação de I/O assíncrono entre outras coisas interessantes.

Aperte os cintos, porque agora sim, vamos começar a ver o negócio na prática!
