Analogia entre mente humana e linguagens de programação
Vocês já perceberam que a maneira como a mente humana executa tarefas é similar à de um software de computador? Quem é programador sabe o que significa quando uma linguagem é single-threaded e eu digo para vocês que, por mais incrível que uma pessoa multitarefa seja, no fundo… no fundo, o funcionamento dela é análogo a uma linguagem de programação monotarefa com um excelente gerenciador de loop de eventos, como, por exemplo, o JavaScript.
Eu fui enganado a vida inteira, pois eu acreditava que o JavaScript podia executar tarefas em paralelo, o que, na realidade, é uma grande mentira. O JavaScript é tão monotarefa quanto o PHP e a única diferença entre os dois é que o JavaScript possui um gerenciador de loop de eventos nativo.
Eu sou como o PHP, só consigo executar tarefas sequencialmente do começo ao fim e demoro para alternar entre uma tarefa e outra, essa é uma limitação minha. Já uma pessoa multitarefas é como um programa em JavaScript, esse tipo de pessoa concilia várias tarefas tão bem que dá a ilusão de que ela está executando tudo em paralelo, porém, assim como os computadores, as pessoas só conseguem processar uma informação de cada vez o que faz com que todas elas sejam essencialmente single-threaded ou “monotarefas”. O que torna uma pessoa multitarefas tão excelente é a sua habilidade em coordenar essas tarefas, assim como o JavaScript faz com suas promessas em segundo plano. Uma pessoa multitarefas consegue alternar entre uma tarefa e outra sem interromper o fluxo de execução, enquanto uma pessoa monotarefa só consegue fazer uma tarefa por vez e possui dificuldades para alternar entre uma tarefa e outra devido ao seu problema de atenção alternada.
Como uma pessoa multitarefas funciona? Antes de tudo, para haver execução real de tarefas em paralelo são necessários dois programas distintos. Um único programa só consegue fazer uma tarefa por vez e o máximo que ele consegue fazer é conciliar várias tarefas através do gerenciador de eventos, o mesmo princípio se aplica a pessoas multitarefas, para haver execução paralela real de tarefas você precisa de duas pessoas assim como você precisa de dois programas de computador. Uma única pessoa só consegue conciliar suas tarefas, mas ela jamais consegue fazer duas em simultâneo.
Não acredita em mim? Então veja:
const fn = async (name) =>
new Promise((resolve) => {
for (let i = 1; i <= 3; i++) {
console.debug(`${name}: ${i}`);
}
resolve();
});
Promise.all([fn('a'), fn('b'), fn('c')]);
// a: 1
// a: 2
// a: 3
// b: 1
// b: 2
// b: 3
// c: 1
// c: 2
// c: 3
Esse código prova que o JavaScript de paralelo não tem nada! Ele empilha as tarefas, executa uma por uma e finaliza o programa. Podemos dizer que é dessa forma como uma pessoa monotarefa funciona.
const fn = async (name) =>
new Promise((resolve) => {
let i = 1;
const loop = () => {
if (i <= 3) {
console.debug(`${name}: ${i}`);
i++;
setTimeout(loop, 0);
}
};
loop();
resolve();
});
Promise.all([fn('a'), fn('b'), fn('c')]);
// a: 1
// b: 1
// c: 1
// a: 2
// b: 2
// c: 2
// a: 3
// b: 3
// c: 3
Já esse programa ilustra como a mente de uma pessoa multitarefas funciona,
ele alterna entre uma tarefa e outra e finaliza todas de uma vez. Para os
desavisados isso pode passar a impressão de que o programa está executando todas
as promessas simultaneamente, mas engana-se quem pensa dessa forma. Ao chamar a
função setTimeout() você está liberando o gestor de eventos do JavaScript para
executar a próxima promessa na pilha, em outras palavras, isso equivale a uma
pessoa deixando uma tarefa pela metade e partindo para outra. Em essência, as
duas pessoas só conseguem fazer uma coisa de cada vez e a diferença está na
forma como elas administram.
Entenda uma coisa, não existe paralelismo real em uma única thread de computador, para haver paralelismo você precisa de dois ou mais programas1. O mesmo se aplica às pessoas, ninguém consegue fazer duas tarefas simultaneamente, o máximo que você pode fazer é delegar algumas funções para o seu piloto automático e usar a sua atenção para outras coisas, da mesma forma como o JavaScript delega suas promessas para o gerenciador de loop de eventos e deixa a linha de execução principal livre para as demais tarefas.
Um exemplo: imagine que você está dirigindo o carro enquanto ouve uma conversa no rádio. Quem você acha que está dirigindo? É o seu piloto automático. A sua atenção está virada para o que está sendo transmitido no rádio. Logicamente você vai alternar a atenção para o que está na estrada a fim de não se acidentar, mas por norma, você não consegue prestar atenção nas duas coisas simultaneamente. No JavaScript, o piloto automático é análogo ao gerenciador de loop de eventos enquanto a consciência plena é análoga à linha de execução principal.
Portanto, é falsa essa impressão de que pessoas multitarefas conseguem fazer várias coisas “ao mesmo tempo”, pois o que acontece na realidade é justamente a alternância entre uma atividade e outra, de uma pessoa que, na mais pura essência, é um ser monotarefa com atenção limitada. Enquanto um tipo de pessoa consegue conciliar várias atividades a outra possui dificuldades em mudar a sua atenção. No final das contas, as duas são monotarefas, então não fique se cobrando por não ser uma pessoa multitarefas que “faz tudo”.
E você? Se considera uma pessoa “PHP” ou “JavaScript”?
quando digo que não existe paralelismo real numa única thread, quero dizer que o programa só consegue executar uma coisa por vez. Para existir paralelismo de verdade, é preciso ter múltiplas threads ou até mesmo processos distintos, o que, na prática, equivale a rodar “vários programas” simultaneamente. ↩︎