# 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!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://concorrencia101.leandronsp.com/parte-ii-concorrencia-em-diferentes-linguagens/definindo-ambientes-de-execucao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
