Pourquoi JavaScript ne prend-il pas en charge le multithreading?


269

Est-ce une décision de conception délibérée ou un problème avec nos navigateurs actuels qui sera corrigé dans les prochaines versions?


3
Voir également les réponses à la question JavaScript et Threads pour plus d'informations sur les travailleurs Web / threads de travail
Sam Hasler

115
Bonjour, cher Googler. Vous remarquerez peut-être que tout ici semble être assez daté (notez que cette question a été posée il y a plus de 5 ans.) Depuis qu'elle a été posée, les navigateurs Web ont acquis certaines capacités qui, à ma connaissance, sont plus ou moins multithreads. Jetez un œil à Web Workers: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare

2
Multithread.js enveloppe Web Workers et permet un multithreading facile dans JS. Fonctionne sur tous les nouveaux navigateurs, y compris iOS Safari. :)
kwh

1
Copie possible de JavaScript et de threads
Matt

Réponses:


194

JavaScript ne prend pas en charge le multithread car l'interpréteur JavaScript dans le navigateur est un thread unique (AFAIK). Même Google Chrome ne laissera pas le JavaScript d'une seule page Web s'exécuter simultanément, car cela entraînerait d'énormes problèmes de concurrence dans les pages Web existantes. Tout ce que Chrome fait est de séparer plusieurs composants (différents onglets, plug-ins, etc.) dans des processus distincts, mais je ne peux pas imaginer une seule page ayant plus d'un thread JavaScript.

Vous pouvez toutefois utiliser, comme cela a été suggéré, setTimeoutpour autoriser une sorte de planification et de concurrence simultanée «fausse». Le navigateur reprend ainsi le contrôle du thread de rendu et démarre le code JavaScript fourni setTimeoutaprès le nombre de millisecondes donné. Ceci est très utile si vous souhaitez autoriser la fenêtre (ce que vous voyez) à actualiser tout en effectuant des opérations dessus. Le simple fait de parcourir les coordonnées et de mettre à jour un élément en conséquence vous permettra simplement de voir les positions de début et de fin, et rien entre les deux.

Nous utilisons une bibliothèque d'abstraction en JavaScript qui nous permet de créer des processus et des threads qui sont tous gérés par le même interpréteur JavaScript. Cela nous permet d'exécuter des actions de la manière suivante:

  • Processus A, fil 1
  • Processus A, fil 2
  • Processus B, fil 1
  • Processus A, fil 3
  • Processus A, fil 4
  • Processus B, fil 2
  • Suspendre le processus A
  • Processus B, fil 3
  • Processus B, fil 4
  • Processus B, fil 5
  • Démarrer le processus A
  • Processus A, fil 5

Cela permet une certaine forme de planification et un faux parallélisme, le démarrage et l'arrêt des threads, etc., mais ce ne sera pas un vrai multi-threading. Je ne pense pas qu'il sera jamais implémenté dans la langue elle-même, car le vrai multi-thread n'est utile que si le navigateur peut exécuter une seule page multi-thread (ou même plus d'un noyau), et les difficultés y sont beaucoup plus grandes que les possibilités supplémentaires.

Pour l'avenir de JavaScript, consultez ceci: https://developer.mozilla.org/presentations/xtech2006/javascript/


73
Je pense que jamais mis en œuvre est une vision trop étroite. Je garantis que les applications Web pourront éventuellement être véritablement multithread (c'est logique, car les applications Web deviennent plus dominantes et le matériel devient plus parallèle), et comme je le vois, puisque JavaScript est le langage de facto du développement Web, il devra éventuellement prendre en charge le multithreading ou être remplacé par quelque chose qui le fait.
devios1

6
Jamais n'est probablement un peu une déclaration trop audacieuse :) mais je pense toujours que les avantages du vrai javascript multithread ne sont pas réalisables dans un avenir prévisible;)
Kamiel Wanrooij

5
Bien que je soutienne que les travailleurs Web sont plus simultanés via un modèle de processus qu'un modèle de thread. Les travailleurs du Web utilisent le passage de messages comme moyen de communication, ce qui est une solution élégante aux problèmes de concurrence «habituels» dans les applications multithread. Je ne sais pas s'ils peuvent réellement fonctionner simultanément sur les mêmes objets que la page principale. Ils ne peuvent pas accéder au DOM pour autant que je sache. La plupart de cela est sémantique cependant, les travailleurs du web semblent prometteurs à toutes fins utiles.
Kamiel Wanrooij

les difficultés sont bien plus grandes que les possibilités supplémentaires Je ne sais pas si vous pensez à toutes les possibilités supplémentaires. Je pense particulièrement aux cas où webgl est utilisé comme dans les jeux ou les visualisations graphiques. Par exemple, considérons la nouvelle version 3D de Google Maps. Dans les villes avec de nombreux modèles 3D, mon PC a besoin d'environ 2 minutes pour tout charger lorsque de nombreuses maisons doivent être rendues. Sous certains angles, ni ma carte graphique ni mon réseau ne fonctionnent à pleine capacité. Mais 1 des 8 processeurs est à 100%. Le multithreading est également une grande préoccupation en termes de fps comme le montre cet exemple: youtube.com/watch?v=sJ2p982cZFc
Scindix

25

Le multi-threading JavaScript (avec certaines limitations) est ici. Google a implémenté des employés pour Gears, et les employés sont inclus avec HTML5. La plupart des navigateurs ont déjà ajouté la prise en charge de cette fonctionnalité.

La sécurité des threads des données est garantie car toutes les données communiquées à / du travailleur sont sérialisées / copiées.

Pour plus d'informations, lisez:

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

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


8
Mais n'est-ce pas davantage une approche multi-processus plutôt que multi-thread? Les threads sont connus pour fonctionner dans un seul tas.
beefeather

1
@beefeather, c'est vrai. Il s'agit davantage d'une approche processus.
Neil

23

Traditionnellement, JS était destiné à des morceaux de code courts et rapides. Si vous aviez des calculs majeurs en cours, vous l' avez fait sur un serveur - l'idée d'un JS + HTML app qui ont fonctionné dans votre navigateur pendant de longues périodes de temps à faire des choses non-triviales était absurde.

Bien sûr, nous avons maintenant cela. Mais il faudra un peu de temps aux navigateurs pour rattraper leur retard - la plupart d'entre eux ont été conçus autour d'un modèle à un seul thread, et changer ce n'est pas facile. Google Gears contourne de nombreux problèmes potentiels en exigeant que l'exécution en arrière-plan soit isolée - pas de changement du DOM (car ce n'est pas sûr pour les threads), pas d'accès aux objets créés par le thread principal (idem). Bien que restrictif, ce sera probablement la conception la plus pratique pour un avenir proche, à la fois parce qu'elle simplifie la conception du navigateur et parce qu'elle réduit le risque de permettre aux codeurs JS inexpérimentés de jouer avec les threads ...

@marcio :

Pourquoi est-ce une raison pour ne pas implémenter le multi-threading en Javascript? Les programmeurs peuvent faire ce qu'ils veulent avec les outils dont ils disposent.

Alors, ne leur donnons pas des outils qui sont si faciles à utiliser à mauvais escient que tous les autres sites Web que j'ouvre finissent par planter mon navigateur. Une implémentation naïve de cela vous amènerait directement dans le territoire qui a causé tant de maux de tête à MS pendant le développement d'IE7: les auteurs de modules complémentaires ont joué rapidement et avec le modèle de thread, entraînant des bogues cachés qui sont devenus évidents lorsque les cycles de vie des objets ont changé sur le thread principal . MAUVAIS. Si vous écrivez des modules complémentaires ActiveX multi-thread pour IE, je suppose que cela vient avec le territoire; ne signifie pas qu'il doit aller plus loin que cela.


6
"cela réduit le risque impliqué> de permettre aux codeurs JS inexpérimentés> de jouer avec les threads" Pourquoi est-ce une raison pour ne pas implémenter le multi-threading en Javascript? Les programmeurs peuvent faire ce qu'ils veulent avec les outils dont ils disposent. Si c'est bon ou mauvais, c'est leur problème. Avec le modèle de processus Google Chrome, il ne peut même pas affecter d'autres applications. :)
Marcio Aguiar

3
@ Shog9 - "Ne donnons pas aux [programmeurs] des outils qui sont si faciles à utiliser à mauvais escient que tous les autres sites Web que j'ouvre finissent par planter mon navigateur." - Quelle? Selon cette même logique, aucun langage ne devrait avoir le multithreading, car s'ils proposaient que tous les autres programmes que vous essayez d'ouvrir se plantent. Sauf que ça ne marche pas comme ça. Le filetage existe dans la plupart des langues et la plupart des programmeurs novices n'y touchent pas, et la plupart de ceux qui ne le mettent pas en production, et ces applications qui ne sont jamais devenues populaires ou largement utilisées.
ArtOfWarfare

11

Je ne connais pas la justification de cette décision, mais je sais que vous pouvez simuler certains des avantages de la programmation multithread en utilisant setTimeout. Vous pouvez donner l'illusion de plusieurs processus faisant les choses en même temps, bien qu'en réalité, tout se passe dans un seul fil.

Demandez à votre fonction de faire un peu de travail, puis appelez quelque chose comme:

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

Et toutes les autres choses à faire (comme les mises à jour de l'interface utilisateur, les images animées, etc.) se produiront lorsqu'elles en auront l'occasion.


La plupart des cas, je voudrais utiliser un loopintérieur setTimeoutmais apparemment cela ne fonctionne pas. Avez-vous fait quelque chose comme ça ou avez-vous un hack? un exemple serait pour le tableau de 1000 éléments, je m'attends à en utiliser deux pour les boucles à l'intérieur de deux setTimeoutappels de telle sorte que le premier boucle à travers et élément d'impression 0..499, le second boucle à travers et élément d'impression 500..999.
benjaminz

Habituellement, la technique consiste à enregistrer l'état et à continuer. Par exemple, supposons que vous souhaitiez imprimer de 0 à 1000, vous pouvez imprimer de 0 à 499, puis effectuer l'astuce setTimeout avec l'argument 500. Le code qu'il contient devrait prendre l'argument (500) et démarrer la boucle à partir de là.
Eyal

8

Voulez-vous dire pourquoi le langage ne prend-il pas en charge le multithreading ou pourquoi les moteurs JavaScript dans les navigateurs ne prennent-ils pas en charge le multithreading?

La réponse à la première question est que JavaScript dans le navigateur est destiné à être exécuté dans un bac à sable et d'une manière indépendante de la machine / du système d'exploitation, ajouter un support multithreading compliquerait la langue et lierait la langue trop étroitement au système d'exploitation.


6

Node.js 10.5+ prend en charge les threads de travail comme fonctionnalité expérimentale (vous pouvez l'utiliser avec l' indicateur --experimental-worker activé): https://nodejs.org/api/worker_threads.html

Donc, la règle est:

  • si vous devez faire des opérations liées aux E / S , utilisez le mécanisme interne (aussi appelé rappel / promesse / async-wait)
  • si vous devez effectuer des opérations liées au processeur , utilisez des threads de travail.

Les threads de travail sont destinés à être des threads à longue durée de vie, ce qui signifie que vous générez un thread d'arrière-plan, puis vous communiquez avec lui via le passage de messages.

Sinon, si vous devez exécuter une lourde charge CPU avec une fonction anonyme, vous pouvez utiliser https://github.com/wilk/microjob , une petite bibliothèque construite autour de threads de travail.


4

Comme Matt B l'a dit, la question n'est pas très claire. En supposant que vous posez des questions sur la prise en charge du multithreading dans la langue: car elle n'est pas nécessaire pour 99,999% des applications en cours d'exécution dans le navigateur actuellement. Si vous en avez vraiment besoin, il existe des solutions de contournement (comme l'utilisation de window.setTimeout).

En général, le multithreading est très, très, très, très, très, très difficile (ai-je dit que c'est difficile?) De bien faire les choses, sauf si vous introduisez des restrictions supplémentaires (comme utiliser uniquement des données immuables).




1

Ce sont les implémentations qui ne prennent pas en charge le multithread. Actuellement, Google Gears fournit un moyen d'utiliser une certaine forme de concurrence en exécutant des processus externes, mais c'est à peu près tout.

Le nouveau navigateur que Google est censé publier aujourd'hui (Google Chrome) exécute du code en parallèle en le séparant en cours.

Le langage de base, bien sûr, peut avoir le même support que, disons Java, mais le support de quelque chose comme la concurrence d'Erlang est loin d'être à l'horizon.


1

Javascript est une langue à fil unique. Cela signifie qu'il a une pile d'appels et un tas de mémoire. Comme prévu, il exécute le code dans l'ordre et doit terminer l'exécution d'un code pièce avant de passer au suivant. C'est synchrone, mais cela peut parfois être dangereux. Par exemple, si une fonction met un certain temps à s'exécuter ou doit attendre quelque chose, elle gèle tout en attendant.


0

D'après ce que j'ai entendu, Google Chrome aura du javascript multithread, donc c'est un problème "d'implémentations actuelles".


0

Sans prise en charge linguistique appropriée pour la synchronisation des threads, il n'est même pas logique que de nouvelles implémentations essaient. Les applications JS complexes existantes (par exemple, tout ce qui utilise ExtJS) se bloqueraient très probablement de manière inattendue, mais sans synchronizedmot - clé ou quelque chose de similaire, il serait également très difficile, voire impossible, d'écrire de nouveaux programmes qui se comportent correctement.


-1

Cependant, vous pouvez utiliser la fonction eval pour amener la concurrence à un certain degré

/* 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

Le multi-threading avec javascript est clairement possible en utilisant des webworkers apportés par HTML5.

La principale différence entre les travailleurs Web et un environnement multi-threading standard est que les ressources mémoire ne sont pas partagées avec le thread principal, une référence à un objet n'est pas visible d'un thread à l'autre. Les threads communiquent en échangeant des messages, il est donc possible de mettre en œuvre un algorithme de synchronisation et d'appel de méthode simultanée suivant un modèle de conception piloté par les événements.

Il existe de nombreux frameworks permettant de structurer la programmation entre les threads, parmi eux OODK-JS, un framework OOP js supportant la programmation simultanée https://github.com/GOMServices/oodk-js-oop-for-js


5
Le partage de mémoire est la définition exacte d'un thread opposé à un processus séparé (par exemple fork () vs exec ()). Les threads peuvent partager des objets, les processus doivent utiliser IPC. Les travailleurs Web ne sont pas multithreads.
felixfbecker
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.