为什么JavaScript不支持多线程?

时间:2008-09-02 16:03:24

标签: javascript multithreading browser

这是一个刻意的设计决定还是我们当前浏览器的问题,将在未来的版本中得到纠正?

18 个答案:

答案 0 :(得分:164)

JavaScript不支持多线程,因为浏览器中的JavaScript解释器是单线程(AFAIK)。即使谷歌Chrome也不会让单个网页的JavaScript同时运行,因为这会在现有网页中造成大量并发问题。所有Chrome确实将单独的多个组件(不同的选项卡,插件等)分离到单独的进程中,但我无法想象单个页面具有多个JavaScript线程。

然而,正如所建议的,您可以使用setTimeout来允许某种调度和“假”并发。这会导致浏览器重新获得对呈现线程的控制,并在给定的毫秒数后启动提供给setTimeout的JavaScript代码。如果要在对其执行操作时允许视口(您看到的内容)进行刷新,这非常有用。只是循环通过例如相应地坐标和更新元素只会让你看到开始和结束位置,而不介于两者之间。

我们在JavaScript中使用抽象库,允许我们创建由同一JavaScript解释器管理的进程和线程。这允许我们以下列方式运行操作:

  • 流程A,主题1
  • 流程A,线程2
  • 流程B,主题1
  • 流程A,主题3
  • 流程A,主题4
  • 流程B,线程2
  • 暂停流程A
  • 流程B,主题3
  • 流程B,主题4
  • 流程B,主题5
  • 启动流程A
  • 流程A,主题5

这允许某种形式的调度和伪造并行,线程的启动和停止等,但它不会是真正的多线程。我认为它不会在语言本身中实现,因为真正的多线程只有在浏览器可以运行单个页面多线程(甚至多个核心)时才有用,并且存在更大的困难而不是额外的可能性。

对于JavaScript的未来,请查看: https://developer.mozilla.org/presentations/xtech2006/javascript/

答案 1 :(得分:22)

传统上,JS旨在用于简短,快速运行的代码片段。如果您正在进行重大计算,那么您是在服务器上完成的 - 在浏览器中长时间运行的JS + HTML 应用程序的想法是非常荒谬的。

当然,现在我们有了。但是,浏览器需要花费一些时间才能赶上 - 大多数都是围绕单线程模型设计的,改变这一点并不容易。 Google Gears通过要求后台执行被隔离来解决许多潜在问题 - 不更改DOM(因为这不是线程安全的),不访问主线程创建的对象(同上)。虽然限制性,但这可能是不久的将来最实用的设计,因为它简化了浏览器的设计,并且因为它降低了允许没有经验的JS编码人员乱用线程所涉及的风险......

@marcio

  

为什么这不是在Javascript中实现多线程的原因?程序员可以使用他们拥有的工具做任何他们想做的事。

那么,我们不要给他们那些容易误用的工具,以至于我打开的每个其他网站都会崩溃我的浏览器。这种天真的实现会让你直接进入导致MS在IE7开发过程中出现如此多头痛的领域:附加作者使用线程模型快速而松散地运行,导致隐藏的错误在主线程上对象生命周期发生变化时变得明显。坏。如果您正在为IE编写多线程ActiveX加载项,我想它是随着领域而来的;并不意味着它需要更进一步。

答案 2 :(得分:19)

JavaScript多线程(有一些限制)就在这里。谷歌为Gears实施了工作人员,HTML5中包含了工作人员。大多数浏览器已经添加了对此功能的支持。

数据的线程安全性得到保证,因为与工作者之间传递的所有数据都是序列化/复制的。

有关详细信息,请阅读:

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

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

答案 3 :(得分:10)

我不知道这个决定的基本原理,但我知道您可以使用setTimeout模拟多线程编程的一些好处。你可以同时给出多个进程做事的错觉,但实际上,所有事情都发生在一个线程中。

让你的函数做一些工作,然后调用类似的东西:

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

当他们有机会时,任何其他需要做的事情(如UI更新,动画图像等)都会发生。

答案 4 :(得分:10)

Multithread.js包装Web Workers并允许在JS中轻松进行多线程处理。适用于所有新浏览器,包括iOS Safari。 :)

答案 5 :(得分:7)

你的意思是为什么语言不支持多线程或为什么浏览器中的JavaScript引擎不支持多线程?

第一个问题的答案是浏览器中的JavaScript意味着在沙箱中运行并且以机器/ OS独立的方式运行,添加多线程支持会使语言复杂化并将语言与OS过于紧密地联系起来

答案 6 :(得分:4)

正如亚光b所说,问题不是很清楚。假设您询问该语言中的多线程支持:因为目前在浏览器中运行的应用程序不需要99.999%。如果你真的需要它,有一些解决方法(比如使用window.setTimeout)。

一般来说,多线程非常,非常,非常,非常非常难(我说这很难吗?)要正确,除非你加入额外的限制(比如只使用不可变数据)。

答案 7 :(得分:3)

英特尔一直在Javascript中对多线程进行一些开源研究,最近在GDC 2012上展示了它。 以下是video的链接。该研究小组使用OpenCL,主要关注英特尔芯片组和Windows操作系统。该项目的代号为RiverTrail,代码可在GitHub上获得

一些更有用的链接:

Building a Computing Highway for Web Applications

答案 8 :(得分:2)

Node.js 10.5+支持工作线程作为实验功能(您可以在启用-experimental-worker 标志的情况下使用它):https://nodejs.org/api/worker_threads.html

因此,规则是:

  • 如果您需要执行 I / O绑定操作,请使用内部机制(aka回调/承诺/异步等待)
  • 如果需要执行 CPU绑定操作,请使用辅助线程。

工作线程旨在用作长寿线程,这意味着您生成了一个后台线程,然后通过消息传递与其进行通信。

否则,如果您需要使用匿名函数执行沉重的CPU负载,则可以使用 https://github.com/wilk/microjob ,这是一个围绕工作线程建立的小型库。

答案 9 :(得分:2)

目前有些浏览器支持多线程。因此,如果您需要,可以使用特定的库。例如,查看下一个材料:

答案 10 :(得分:1)

Javascript是一种单线程语言。这意味着它具有一个调用堆栈和一个内存堆。如预期的那样,它按顺序执行代码,并且必须先完成执行片段代码,然后才能继续执行下一个代码。它是同步的,但有时可能是有害的。例如,如果某个函数需要一段时间才能执行或必须等待某件事,那么它会同时冻结所有内容。

答案 11 :(得分:1)

这是不支持多线程的实现。目前,Google Gears提供了一种通过执行外部流程来使用某种形式的并发的方法,但这就是它。

谷歌应该今天发布的新浏览器(谷歌浏览器)通过将其分离并行执行一些代码。

核心语言当然可以和Java一样具有相同的支持,但是对Erlang的并发性的支持远远不够。

答案 12 :(得分:0)

如果没有适当的语言支持进行线程同步,那么尝试新的实现就没有意义。现有的复杂JS应用程序(例如使用ExtJS的任何东西)很可能会意外崩溃,但如果没有synchronized关键字或类似的东西,编写行为正确的新程序也会非常困难甚至不可能。

答案 13 :(得分:0)

但是,您可以使用eval函数将并发性带到某个范围

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

答案 14 :(得分:0)

根据 this article ,已经可以实现JavaScript线程。

答案 15 :(得分:0)

您可以使用jetworker,webworker上的包装器 https://github.com/uxitten/jetworker

答案 16 :(得分:0)

据我所知,谷歌Chrome会有多线程的javascript,所以这是一个“当前实现”的问题。

答案 17 :(得分:-2)

使用HTML5带来的网络工作者显然可以使用javascript进行多线程处理。

Web工作者和标准多线程环境之间的主要区别是内存资源不与主线程共享,从一个线程到另一个线程不能看到对象的引用。线程通过交换消息进行通信,因此可以在事件驱动的设计模式之后实现同步和并发方法调用算法。

许多框架允许在线程之间构建编程,其中包括OODK-JS,一个支持并发编程的OOP js框架 https://github.com/GOMServices/oodk-js-oop-for-js