Por que o JavaScript não suporta multithreading?


269

É uma decisão deliberada de design ou um problema com nossos navegadores atuais que serão corrigidos nas próximas versões?


3
Consulte também as respostas para a pergunta JavaScript e Threads para obter informações sobre trabalhadores da Web / threads de trabalho.
Sam Hasler

115
Olá, companheiro Googler. Você pode perceber que tudo aqui parece estar bastante datado (observe que essa pergunta foi feita há mais de 5 anos). Desde que foi feita, os navegadores da Web ganharam alguns recursos que, até onde eu sei, são mais ou menos multithreading. Dê uma olhada na Web Workers: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare

2
O Multithread.js envolve Web Workers e permite multithreading fácil em JS. Funciona em todos os novos navegadores, incluindo o iOS Safari. :)
kwh

1
Possível duplicado de JavaScript e Threads
Matt

Respostas:


194

O JavaScript não suporta multiencadeamento porque o interpretador JavaScript no navegador é um encadeamento único (AFAIK). Mesmo o Google Chrome não permitirá que o JavaScript de uma única página da web seja executado simultaneamente, pois isso causaria grandes problemas de simultaneidade nas páginas da web existentes. Tudo o que o Chrome faz é separar vários componentes (guias diferentes, plug-ins, etc.) em processos separados, mas não consigo imaginar uma única página com mais de um encadeamento JavaScript.

No entanto, você pode usar, como sugerido, setTimeoutpara permitir algum tipo de agendamento e simultaneidade "falsa". Isso faz com que o navegador recupere o controle do encadeamento de renderização e inicie o código JavaScript fornecido setTimeoutapós o número especificado de milissegundos. Isso é muito útil se você deseja permitir que a viewport (o que você vê) seja atualizada enquanto executa operações nela. Apenas percorrer, por exemplo, as coordenadas e atualizar um elemento de acordo, permitirá que você veja as posições inicial e final, e nada no meio.

Usamos uma biblioteca de abstração em JavaScript que nos permite criar processos e threads que são todos gerenciados pelo mesmo intérprete de JavaScript. Isso nos permite executar ações da seguinte maneira:

  • Processo A, Tópico 1
  • Processo A, Thread 2
  • Processo B, Rosca 1
  • Processo A, Thread 3
  • Processo A, Thread 4
  • Processo B, Thread 2
  • Pausar o Processo A
  • Processo B, Thread 3
  • Processo B, Rosca 4
  • Processo B, Rosca 5
  • Iniciar processo A
  • Processo A, Thread 5

Isso permite alguma forma de programação e paralelismo de falsificações, início e parada de threads, etc., mas não será verdadeiro multi-threading. Eu acho que nunca será implementado no próprio idioma, já que o verdadeiro multithread é útil apenas se o navegador puder executar uma única página com vários threads (ou até mais de um núcleo), e as dificuldades são muito maiores. do que as possibilidades extras.

Para o futuro do JavaScript, confira: https://developer.mozilla.org/presentations/xtech2006/javascript/


73
Eu acho que nunca implementado é uma visão muito estreita. Eu garanto que os aplicativos da Web poderão ser verdadeiramente multithread (é lógico, pois os aplicativos da Web se tornam mais dominantes e o hardware se torna mais paralelo) e, a meu ver, já que o JavaScript é a linguagem de fato do desenvolvimento da Web, acabará tendo que suportar multithreading ou ser substituído por algo que o faça.
devios1

6
Nunca é provavelmente um pouco de uma declaração muito ousada :) mas eu ainda acho que as vantagens de verdadeiros multithreaded javascript não são viáveis no futuro previsível;)
Kamiel Wanrooij

5
Embora eu argumentasse que os trabalhadores da Web são mais concorrentes através de um modelo de processo do que de um modelo de encadeamento. Os trabalhadores da Web usam a passagem de mensagens como meio de comunicação, que é uma solução elegante para os problemas de concorrência 'usuais' em aplicativos multithread. Não tenho certeza se eles podem realmente operar nos mesmos objetos que a página principal simultaneamente. Eles não podem acessar o DOM, tanto quanto eu sei. A maior parte disso é semântica, porém, os profissionais da Web parecem promissores para todos os efeitos.
27412 Kamiel Wanrooij

dificuldades são muito maiores do que as possibilidades extras. Não tenho certeza se você pensa em todas as possibilidades extras. Estou pensando especialmente nos casos em que o webgl é usado como em jogos ou visualizações gráficas. Por exemplo, considere a nova versão 3D do Google Maps. Nas cidades com muitos modelos 3D, meu PC precisa de aproximadamente 2 minutos para carregar tudo quando muitas casas precisam ser renderizadas. Em certos ângulos, nem minha placa de vídeo nem minha rede estão funcionando. Mas 1 de 8 processadores está em 100%. Multithreading também é uma grande preocupação em termos de fps como mostra este exemplo: youtube.com/watch?v=sJ2p982cZFc
Scindix

25

O multi-threading JavaScript (com algumas limitações) está aqui. Trabalhadores implementados pelo Google para o Gears, e os trabalhadores estão sendo incluídos no HTML5. A maioria dos navegadores já adicionou suporte para esse recurso.

A segurança do encadeamento de dados é garantida porque todos os dados comunicados ao / do trabalhador são serializados / copiados.

Para mais informações, leia:

http://www.whatwg.org/specs/web-workers/current-work/

http://ejohn.org/blog/web-workers/


8
Mas não é mais uma abordagem multiprocessos em vez de multiencadeados? Sabe-se que os threads funcionam em um único heap.
beefeather

1
@ Beefeather, isso é verdade. É mais uma abordagem de processo.
Neil

23

Tradicionalmente, o JS era destinado a trechos de código curtos e de execução rápida. Se você tinha grandes cálculos em andamento, fazia isso em um servidor - a idéia de um aplicativo JS + HTML que era executado no seu navegador por longos períodos de tempo fazendo coisas não triviais era absurda.

Claro, agora temos isso. Mas demorará um pouco para os navegadores se atualizarem - a maioria deles foi projetada em torno de um modelo de thread único, e mudar isso não é fácil. O Google Gears evita muitos problemas em potencial, exigindo que a execução em segundo plano seja isolada - sem alterar o DOM (já que isso não é seguro para threads), sem acessar objetos criados pelo thread principal (idem). Embora restritivo, esse provavelmente será o design mais prático para o futuro próximo, porque simplifica o design do navegador e reduz o risco de permitir que codificadores JS inexperientes mexam com os threads ...

@marcio :

Por que esse é um motivo para não implementar multi-threading em Javascript? Os programadores podem fazer o que quiserem com as ferramentas que possuem.

Portanto, não vamos dar a eles ferramentas tão fáceis de usar mal que todos os outros sites que eu abro acabam travando meu navegador. Uma implementação ingênua disso o levaria direto ao território que causou tantas dores de cabeça ao MS durante o desenvolvimento do IE7: autores de complementos foram rápidos e frouxos com o modelo de encadeamento, resultando em erros ocultos que se tornaram evidentes quando os ciclos de vida do objeto foram alterados no encadeamento primário . RUIM. Se você está escrevendo complementos ActiveX multithread para o IE, acho que ele vem com o território; não significa que precisa ir além disso.


6
"reduz o risco envolvido> de permitir que codificadores JS inexperientes> mexam nos threads" Por que esse é um motivo para não implementar o multiencadeamento em Javascript? Os programadores podem fazer o que quiserem com as ferramentas que possuem. Se é bom ou ruim, é problema deles. Com o modelo de processo do Google Chrome, ele não pode afetar outros aplicativos. :)
Marcio Aguiar

3
@ Shog9 - "Não vamos fornecer ferramentas [de programadores] tão fáceis de usar mal que todos os outros sites que eu abro acabam travando meu navegador". - O que? Pela mesma lógica, nenhum idioma deveria ter multithreading, porque se eles oferecessem que todos os outros programas que você tentasse abrir travariam. Exceto que não funciona dessa maneira. O encadeamento existe na maioria dos idiomas e a maioria dos programadores iniciantes não o toca, e a maioria daqueles que não o colocam em produção, e os aplicativos que nunca se tornam populares ou amplamente utilizados.
ArtOfWarfare 7/11

11

Não sei a lógica dessa decisão, mas sei que você pode simular alguns dos benefícios da programação multiencadeada usando setTimeout. Você pode dar a ilusão de vários processos fazendo coisas ao mesmo tempo, embora, na realidade, tudo aconteça em um único segmento.

Faça com que sua função faça um pouco de trabalho e chame algo como:

setTimeout(function () {
    ... do the rest of the work...
}, 0);

E qualquer outra coisa que precise ser feita (como atualizações da interface do usuário, imagens animadas etc.) acontecerá quando tiverem uma chance.


Na maioria dos casos, eu gostaria de usar um loopdentro do, setTimeoutmas aparentemente isso não funciona. Você já fez algo assim ou tem um hack? um exemplo seria para uma matriz de 1000 elementos, espero usar dois para loops dentro de duas setTimeoutchamadas, de modo que o primeiro faça um loop e imprima o elemento 0..499, o segundo faça um loop e imprima o elemento 500..999.
benjaminz

Geralmente, a técnica é salvar o estado e continuar. Por exemplo, digamos que você queira imprimir de 0 a 1000, você pode imprimir de 0 a 499 e, em seguida, execute o truque setTimeout com o argumento 500. O código dentro dele saberia pegar o argumento (500) e iniciar o loop a partir daí.
Eyal

8

Você quer dizer por que o idioma não suporta multithreading ou por que os mecanismos JavaScript nos navegadores não suportam multithreading?

A resposta para a primeira pergunta é que o JavaScript no navegador deve ser executado em uma sandbox e de maneira independente da máquina / sistema operacional; adicionar suporte a multithreading complicaria o idioma e amarraria o idioma muito próximo ao sistema operacional.


6

O Node.js 10.5+ suporta threads de trabalho como recurso experimental (você pode usá-lo com o sinalizador --experimental-worker ativado): https://nodejs.org/api/worker_threads.html

Então, a regra é:

  • se você precisar fazer operações de ligação de E / S , use o mecanismo interno (também conhecido como retorno de chamada / promessa / espera assíncrona)
  • se você precisar executar operações vinculadas à CPU , use threads de trabalho.

Os encadeamentos de trabalho devem ser de longa duração, o que significa que você gera um encadeamento em segundo plano e depois se comunica com ele por meio da passagem de mensagens.

Caso contrário, se você precisar executar uma carga pesada da CPU com uma função anônima, poderá acessar https://github.com/wilk/microjob , uma pequena biblioteca criada em torno de threads de trabalho.


4

Assim como matt b disse, a questão não é muito clara. Supondo que você esteja perguntando sobre o suporte a multithreading no idioma: porque não é necessário para 99,999% dos aplicativos em execução no navegador atualmente. Se você realmente precisar, existem soluções alternativas (como usar window.setTimeout).

Em geral, o multithreading é muito, muito, muito, muito, muito, muito difícil (eu disse que é difícil?) Acertar, a menos que você faça restrições extras (como usar apenas dados imutáveis).




1

São as implementações que não suportam multi-threading. Atualmente, o Google Gears está fornecendo uma maneira de usar alguma forma de simultaneidade executando processos externos, mas é isso.

O novo navegador que o Google deve lançar hoje (Google Chrome) executa algum código em paralelo, separando-o em processo.

A linguagem principal, é claro, pode ter o mesmo suporte que, digamos, Java, mas o suporte a algo como a simultaneidade de Erlang não está nem perto do horizonte.


1

Javascript é uma linguagem de thread único. Isso significa que ele possui uma pilha de chamadas e um monte de memória. Como esperado, ele executa o código em ordem e deve concluir a execução de um código de peça antes de passar para o próximo. É síncrono, mas às vezes isso pode ser prejudicial. Por exemplo, se uma função demora um pouco para ser executada ou precisa esperar algo, ela congela tudo enquanto isso.


0

Tanto quanto ouvi dizer, o Google Chrome terá javascript multithread, por isso é um problema de "implementações atuais".


0

Sem o suporte adequado ao idioma para sincronização de encadeamentos, nem faz sentido tentar novas implementações. Aplicativos JS complexos existentes (por exemplo, qualquer coisa usando o ExtJS) provavelmente travariam inesperadamente, mas sem uma synchronizedpalavra - chave ou algo semelhante, também seria muito difícil ou até impossível escrever novos programas que se comportassem corretamente.


-1

No entanto, você pode usar a função eval para trazer simultaneidade PARA ALGUM MOMENTO

/* content of the threads to be run */
var threads = [
        [
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');"
        ],
        [
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');"
        ]
    ];

window.onload = function() {
    var lines = 0, quantum = 3, max = 0;

    /* get the longer thread length */
    for(var i=0; i<threads.length; i++) {
        if(max < threads[i].length) {
            max = threads[i].length;
        }
    }

    /* execute them */
    while(lines < max) {
        for(var i=0; i<threads.length; i++) {
            for(var j = lines; j < threads[i].length && j < (lines + quantum); j++) {
                eval(threads[i][j]);
            }
        }
        lines += quantum;
    }
}

-2

É claramente possível realizar multi-threading com javascript usando os trabalhadores da Web trazidos pelo HTML5.

A principal diferença entre os trabalhadores da Web e um ambiente multithread padrão é que os recursos de memória não são compartilhados com o encadeamento principal, uma referência a um objeto não é visível de um encadeamento para outro. Os encadeamentos se comunicam através da troca de mensagens; portanto, é possível implementar um algoritmo de sincronização e chamada de método simultâneo seguindo um padrão de design orientado a eventos.

Existem muitas estruturas que permitem estruturar a programação entre threads, entre elas o OODK-JS, uma estrutura OOP js que suporta programação simultânea https://github.com/GOMServices/oodk-js-oop-for-js


5
Compartilhar memória é a definição exata de um Thread em oposição a um processo separado (por exemplo, fork () vs exec ()). Threads podem compartilhar objetos, os processos devem usar o IPC. Trabalhadores da Web não são multithreading.
Felixfbecker
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.