为什么 JavaScript 不支持多线程?

IT技术 javascript multithreading browser
2021-01-22 06:57:44

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

6个回答

JavaScript 不支持多线程,因为浏览器中的 JavaScript 解释器是单线程 (AFAIK)。即使是谷歌浏览器也不会让单个网页的 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/

我认为从未实施过的愿景太狭隘了。我保证网络应用程序最终将能够成为真正的多线程(这是合乎逻辑的,因为网络应用程序变得更加主导,硬件变得更加并行),正如我所看到的,由于 JavaScript 是事实上的网络开发语言,它最终将不得不支持多线程或被支持的东西所取代。
2021-03-13 06:57:44
尽管我认为网络工作者通过进程模型比线程模型更具并发性。Web 工作者使用消息传递作为通信手段,这是多线程应用程序中“常见”并发问题的优雅解决方案。我不确定它们是否可以同时对与主页相同的对象进行操作。据我所知,他们无法访问 DOM。虽然其中大部分是语义,但网络工作者看起来对所有意图和目的都有希望。
2021-03-20 06:57:44
困难比额外的可能性大得多,我不确定您是否考虑过所有额外的可能性。我特别考虑在游戏或图形可视化中使用 webgl 的情况。例如,考虑一下新的 3D 版本的谷歌地图。在拥有许多 3D 模型的城市中,当必须渲染许多房屋时,我的 PC 需要大约 2 分钟才能加载所有内容。在某些角度,我的显卡和我的网络都无法正常工作。但是 8 个处理器中有 1 个是 100%。如本示例所示,多线程也是 fps 方面的一个大问题:youtube.com/watch?v=sJ2p982cZFc
2021-03-24 06:57:44
Never 可能有点太大胆了 :) 但我仍然认为真正的多线程 javascript 的优势在可预见的未来是不可行的 ;)
2021-04-09 06:57:44

JavaScript 多线程(有一些限制)就在这里。Google 为 Gears 实现了 worker,并且 worker 被包含在 HTML5 中。大多数浏览器已经添加了对此功能的支持。

数据的线程安全是有保证的,因为所有与 worker 通信的数据都是序列化/复制的。

欲了解更多信息,请阅读:

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

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

@beefeather,这是真的。它更像是一种过程方法。
2021-03-31 06:57:44
但它不是更多的多进程方法而不是多线程吗?已知线程在单个堆中工作。
2021-04-07 06:57:44
WebWorkers 没有共享内存。为了与彼此通信,他们发送消息。消息是内存的副本。这比共享内存要慢。
2021-04-09 06:57:44

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

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

@马尔西奥

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

那么,我们不要给他们提供很容易被滥用的工具,以至于我打开的每个其他网站最终都会使我的浏览器崩溃。一个幼稚的实现会让你直接进入在 IE7 开发过程中导致 MS 如此令人头疼的领域:附加组件作者在线程模型上快速而松散地玩弄,导致隐藏的错误在主线程上的对象生命周期发生变化时变得明显. 坏的。如果您正在为 IE 编写多线程 ActiveX 附加组件,我想它会随附;并不意味着它需要走得更远。

“它降低了所涉及的风险 > 允许没有经验的 JS 编码员 > 搞乱线程” 为什么这是不在 Javascript 中实现多线程的一个原因?程序员可以使用他们拥有的工具为所欲为。不管是好是坏,都是他们的问题。使用 Google Chrome 进程模型,它甚至无法影响其他应用程序。:)
2021-04-06 06:57:44
@Shog9 - “我们不要给 [程序员] 工具,这些工具很容易被滥用,以至于我打开的所有其他网站最终都会使我的浏览器崩溃。” - 什么?按照同样的逻辑,任何语言都不应该具有多线程,因为如果它们提供您尝试打开的所有其他程序都会崩溃。除了它不能那样工作。线程存在于大多数语言中,大多数新手程序员不会接触它,大多数不会将其投入生产,以及那些从未流行或广泛使用的应用程序。
2021-04-06 06:57:44

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

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

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

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

大多数情况下,我想使用loopinside ,setTimeout但显然这不起作用。你有没有做过这样的事情,或者你有黑客吗?一个例子是 1000 个元素的数组,我希望在两个setTimeout调用中使用两个 for 循环,这样第一个循环通过和打印元素0..499,第二个循环通过和打印元素500..999
2021-03-25 06:57:44
通常该技术是保存状态并继续。例如,假设您想打印 0 到 1000,您可以打印 0 到 499,然后使用参数 500 执行 setTimeout 技巧。里面的代码会知道采用参数 (500) 并从那里开始循环。
2021-04-07 06:57:44

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

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