Javascript 我们可以在单线程脚本语言中使用竞争条件吗?
我经常读到,在javascript中,您不必担心竞争条件,因为它是单线程的。但我相信这是因为事件循环的本质。如果Javascrit没有“”特性,它仍然可能存在并发性问题Javascript 我们可以在单线程脚本语言中使用竞争条件吗?,javascript,multithreading,concurrency,race-condition,Javascript,Multithreading,Concurrency,Race Condition,我经常读到,在javascript中,您不必担心竞争条件,因为它是单线程的。但我相信这是因为事件循环的本质。如果Javascrit没有“”特性,它仍然可能存在并发性问题 让我们考虑这个代码片段: 1 var pending = []; 2 document.getElementById("submitBtn").addEventListener(function() { 3 var val = document.getElementById("textBox").value; 4
让我们考虑这个代码片段:
1 var pending = [];
2 document.getElementById("submitBtn").addEventListener(function() {
3 var val = document.getElementById("textBox").value;
4 pending.push(val);
5 });
6 setInterval(function() {
7 processValues(pending);
8 pending = [];
9 }, 3000);
Asume说javascript“”中没有这样的功能,任何事件都可以被抢先运行另一个事件/代码
现在假设执行第7行,突然事件被抢占,以处理第3行的事件。执行第3行和第4行后,从第8行恢复上一个事件。现在,当执行第8行时,pending
中新添加的值将丢失,因为它既不由processValues
函数处理,也不在pending
数组中
即使是单线程,也会发生争用条件。所以,说javascript没有竞争条件是不对的,因为它是单线程的?具体来说,这是因为javascript的特性
编辑
显然,javascript中可能存在竞争条件。我所指的是某种类型的竞争条件,它不会因为javascript的单线程(或?)特性而发生。例如,我上面描述的一个。是的,我们在单线程JavaScript中有竞争条件。只是数量不如多线程代码(前提是您不使用
alert
或confirm
,详见下文)
您首先说“假设没有跑步到完成的功能”,然后描述了一个依赖于此的比赛条件。但这种竞争条件不可能发生,因为正如您所说,JavaScript已经运行到了完成阶段
虽然在JavaScript中确实存在一类我们不必担心的竞争条件,但我们仍然需要担心很多。例如,异步代码总是有可能出现竞争条件。(这就是ajax调用、来自web工作人员的消息等)
下面是一个常见的错误示例,这是一个真实的比赛条件:
var img = document.createElement('img');
img.src = "kittens.png";
img.onload = function() {
console.log("It loaded");
};
document.body.appendChild(img);
那很安全,对吗错误。仅仅因为JavaScript是单线程运行的,并不意味着浏览器是单线程的。当浏览器看到img.src=“kittens.png”
,如果映像在缓存中,则它完全有权在该img
上触发load
事件:该事件将查找任何处理程序,而不会找到任何处理程序,因此在当前代码完成后不会将任何回调排队以运行-并且我们没有看到“it loaded”消息
虽然这是一个基于浏览器的示例,但它是一个一般原则的示例:仅仅因为主机环境运行一个主JavaScript线程,这并不意味着主机环境不是多线程的,而且多线程可能会对我们的单线程代码产生影响
这只是一个例子。但事实上,我们是安全的。例如,如果我们更改上述代码:
var img = document.createElement('img');
img.onload = function() {
console.log("It loaded");
};
img.src = "kittens.png";
document.body.appendChild(img);
doSomethingElse();
…我们知道
doSomethingElse
将在运行之前被调用,在警报和确认函数周围的某些浏览器(我在看你,Mozilla)上会出现一些不愉快的边缘情况。(TL;DR-至少某些版本的Firefox会在等待用户解除警报时触发ajax完成回调)你在哪里读到的?竞态条件在异步代码中很常见。竞态条件可能存在于javascript、WebSocket等的异步部分。对此,如果您感到好奇,我们已经提供了一个深思熟虑的答案:@Jivings@adeneo检查问题的答案@brianvaughn。答案是“竞态条件只能发生在两个或多个线程之间”对于脚本语言,我认为这是不正确的。这把我弄糊涂了。回答得好。尽管我认为问题在于javascript并不是真正的单线程。如果你看到一个简单的Java程序没有启动任何线程或任何东西,也没有异步方法(实际上异步意味着多线程),那么就不可能创建竞争条件,对吗?@maraca:好吧,JavaScript语言对线程是完全沉默的。唯一的线程保证是由主机提供的。web浏览器上的JavaScript可以访问单个UI线程和X个web工作人员。忽略web workers,基于浏览器的JavaScript实际上是单线程的,这就排除了我在回答末尾提到的问题,web workers被非常智能地设计为使用消息事件模型和worker隔离来避免破坏这一点。类似地,NodeJS上的JavaScript由NodeJS保证一个线程。JVM(Rhino,Nashorn)上的JavaScript不是。@t.JCrowder是的,这正是我的观点,你不能将这一点应用于JavaScript,但可能适用于其他语言。@t.J.Crowder你是对的,JavaScript中可能会出现竞争条件。请参阅我的最新问题。