众所周知,JavaScript在所有现代浏览器实现中都是单线程的,但这是在任何标准中指定的还是只是传统?假设JavaScript总是单线程的,这是完全安全的吗?
当前回答
实际上,父窗口可以与拥有自己执行线程的子窗口或兄弟窗口或框架通信。
其他回答
Chrome是多进程的,我认为每个进程都有自己的Javascript代码,但就代码所知,它是“单线程”的。
Javascript中不支持多线程,至少不是显式的,所以没有什么区别。
我已经尝试了@bobince的例子,做了轻微的修改:
<html>
<head>
<title>Test</title>
</head>
<body>
<textarea id="log" rows="20" cols="40"></textarea>
<br />
<button id="act">Run</button>
<script type="text/javascript">
let l= document.getElementById('log');
let b = document.getElementById('act');
let s = 0;
b.addEventListener('click', function() {
l.value += 'click begin\n';
s = 10;
let s2 = s;
alert('alert!');
s = s + s2;
l.value += 'click end\n';
l.value += `result = ${s}, should be ${s2 + s2}\n`;
l.value += '----------\n';
});
window.addEventListener('resize', function() {
if (s === 10) {
s = 5;
}
l.value+= 'resize\n';
});
</script>
</body>
</html>
所以,当你按下运行,关闭警报弹出并执行“单线程”,你应该会看到如下内容:
click begin
click end
result = 20, should be 20
但如果你尝试在Opera或Firefox稳定的Windows上运行这个,并最小化/最大化屏幕上弹出的警告窗口,那么会有这样的东西:
click begin
resize
click end
result = 15, should be 20
我不想说,这是“多线程”,但一些代码在错误的时间执行,我没有预料到这一点,现在我有一个损坏的状态。 最好了解这种行为。
我的答案是肯定的——因为如果浏览器的javascript引擎异步运行,几乎所有现有的(至少所有非平凡的)javascript代码都会崩溃。
再加上HTML5已经指定了Web Workers(用于多线程javascript代码的显式标准化API),在基本javascript中引入多线程是毫无意义的。
(请其他评论者注意:即使setTimeout/setInterval, http请求onload事件(XHR),和UI事件(点击,聚焦等)提供了一个多线程的粗略印象-他们仍然都是沿着单一的时间轴执行-一次一个-所以即使我们事先不知道他们的执行顺序,也没有必要担心外部条件在事件处理程序,定时函数或XHR回调的执行过程中发生变化。)
我想说的是,该规范并没有阻止人们创建一个在多线程上运行javascript的引擎,要求代码执行同步以访问共享对象状态。
我认为单线程非阻塞模式是出于在浏览器中运行javascript的需要,ui不应该阻塞。
Nodejs遵循了浏览器的方法。
然而,Rhino引擎支持在不同的线程中运行js代码。执行不能共享上下文,但可以共享作用域。 对于这个特定的案例,文档说明:
...Rhino保证了对JavaScript对象属性的访问是跨线程的原子性的,但不能保证脚本在同一作用域内同时执行。如果两个脚本同时使用相同的作用域,则脚本负责协调对共享变量的任何访问。”
通过阅读Rhino文档,我得出结论,对于某些人来说,编写一个javascript api也可以生成新的javascript线程,但api将是特定于Rhino的(例如,节点只能生成一个新进程)。
我想,即使是支持多线程的javascript引擎,也应该兼容不考虑多线程或阻塞的脚本。
我认为浏览器和nodejs之间的关系是这样的:
所有的js代码都在一个线程中执行吗?:是的。 js代码可以导致其他线程运行吗?:是的。 这些线程会改变js的执行上下文吗?:没有。但是它们可以(直接/间接地(?))追加到事件队列中 侦听器可以改变执行上下文。但是不要被愚弄,侦听器再次在主线程上原子地运行。
所以,对于浏览器和nodejs(可能还有很多其他引擎)来说,javascript不是多线程的,但引擎本身是多线程的。
关于网络工作者的更新:
网络工作者的存在进一步证明了javascript可以是多线程的,从某种意义上说,有人可以用javascript创建代码,这些代码将在单独的线程上运行。
然而,web工作者并不能解决那些可以共享执行上下文的传统线程的问题。上面的规则2和3仍然适用,但这次线程代码是由用户(js代码作者)在javascript中创建的。
从效率(而不是并发性)的角度来看,唯一需要考虑的是衍生线程的数量。见下文:
关于线程安全:
The Worker interface spawns real OS-level threads, and mindful programmers may be concerned that concurrency can cause “interesting” effects in your code if you aren't careful. However, since web workers have carefully controlled communication points with other threads, it's actually very hard to cause concurrency problems. There's no access to non-threadsafe components or the DOM. And you have to pass specific data in and out of a thread through serialized objects. So you have to work really hard to cause problems in your code.
P.S.
除了理论之外,对可能出现的极端情况和公认答案中描述的错误要时刻做好准备
Javascript引擎必须是单线程,但Javascript运行时不需要是单线程。
Javascript引擎是什么?这是执行实际JS代码的解释器。引擎需要主机。它不能自己运行。主机是Javascript运行时。
例如,运行在Chrome浏览器中的V8引擎是单线程的。Chrome浏览器是一个运行时&它有其他进程/线程支持V8引擎。
你可以查看这篇文章,在那里有漂亮的解释。如果有帮助的话,别忘了回复并点赞:)
推荐文章
- javascript toISOString()忽略时区偏移
- 如何在JavaScript中获得当前时间
- 我如何从一个元标签与JavaScript的信息?
- 匹配精确字符串
- Haskell对Node.js的响应是什么?
- 用JavaScript创建一个基于字符串的十六进制颜色
- JavaScript数据网格数百万行
- 我可以在JavaScript中获得当前运行函数的名称吗?
- 如何防止输入键提交网页表单?
- 在html文本框中设置键盘插入符号的位置
- 使用jQuery选择多个类
- Cypress:只运行一个测试
- 如何同步确定JavaScript Promise的状态?
- 在Link react-router中传递道具
- 我如何承诺本地XHR?