在很多网站上都说JavaScript是单线程的。当他们这样说时,他们是指JavaScript运行时吗?
我可能误解了一些东西,但JavaScript不仅仅是一种编程语言,你用它创建的程序应该是标记为单线程的程序吗?但也许我不理解某些事情,所以有人可以解释一下我没有得到的东西吗?
答案 0 :(得分:5)
JavaScript,即语言,对于线程主题几乎没有提及。它的单线程还是多线程是否与其运行环境有关。有单线程JavaScript环境和多线程JavaScript环境。规范唯一真正的要求是一个线程有一个job queue,一旦一个作业(一个代码运行,比如对一个事件处理程序的调用)启动,它就会在线程上运行完成该队列中的另一个作业已启动。也就是说,JavaScript具有运行到完成语义。
浏览器上的JavaScript不是单线程的,并且已经多年没有了。有一个主线程(处理UI的线程)和任意数量的web worker线程。网络工作者无法直接访问用户界面,他们向网络线程发送信息,并进行用户界面更新。线程不直接共享数据,它们通过消息传递明确地共享数据。与多线程访问UI和相同的公共数据区域相比,这种分离使编程多线程代码变得非常简单并且不易出错。 (编写正确的多线程代码,任何线程都可以随时访问任何内容很难。)
在浏览器之外,NodeJS中的JavaScript在单个线程上运行。有一个Node的分支来添加多线程,但我认为它不会去任何地方。
JVM(Rhino,Nashorn)上的JavaScript一直是多线程的,由JVM的线程工具支持。
答案 1 :(得分:2)
虽然TJC的答案当然是正确的,但我不认为它解决了人们在说“JavaScript是单线程”时的实际含义问题。他们实际总结(不准确)的是,运行时必须表现得好像有一个执行线程,不能被抢占,哪些必须运行完成。只要最终结果以这种方式运行,实际运行时就可以做任何它喜欢的事情。
这意味着虽然JavaScript程序可能看起来与大量相互交互的线程大规模并行,但它实际上并不是那种类型。内核使用队列,事件循环和简要描述的运行完成语义({3}}来控制所有内容。
这与硬件描述语言(VHDL,Verilog,SystemC(虽然实际上不是语言)等)面临的问题完全相同。它们通过在“进程”之间具有运行时内核循环来给出大规模并行性的错觉,这些循环不是可抢占的,并且必须运行直到定义的挂起点。这一点是为了确保模型以确定的,可重复的方式执行。
HDL和JS之间的区别在于,它是非常明确的,也是HDL的基础,而它则掩盖了JS。这是here的摘录,简要介绍了它 - 例如,它在SystemC LRM中的定义要好得多。
由于流程实例不间断地执行,因此只有一个 流程实例可以在任何时间运行,而不是其他进程 实例可以执行直到当前正在执行的流程实例 已经控制了内核。一个过程不应该先发制人或 中断另一个进程的执行。这被称为 协同常规语义或合作多任务。