maj*_*aja 4 javascript multithreading synchronization thread-safety race-condition
让我们知道我有如下代码:
var shared = 100;
function workWithIt(){
shared += 100;
}
setTimeout(workWithIt, 500);
setTimeout(workWithIt, 500);
Run Code Online (Sandbox Code Playgroud)
理想情况下,这段代码应该为变量添加200 shared,之后为300.
但是,正如我所知c,如果将操作+ =拆分为多个命令,可能会产生一些影响.
可以说,这是函数的执行顺序:
setTimeout() --> create Thread A
setTimeout() --> create Thread B
wait 500ms
**Thread A** | **Thread B**
--------------------------------+---------------------------------
var tmpA = shared; //100 |
| var tmpB = shared; //100
| tmpB = tmpB+100; //tmpB=200
| shared = tmpB;
tmpA = tmpA+100; //tmpA=200 |
shared = tmpA; |
Run Code Online (Sandbox Code Playgroud)
在这种情况下,shared现在值为200.
这可能发生在许多编程语言中,如c,c ++,java,c#,...... - 但是它也可以在Javascript中发生吗?
或者更一般地说:Javascript如何处理其线程,何时在线程之间切换,是否有内置方法,可用于处理竞争条件?
JavaScript代码只有一个显式执行线程.您所描述的场景永远不会在JavaScript中发生.计时器回调只是另一种事件,所有事件都被序列化,以便由浏览器UI线程的相同核心事件循环顺序执行.
因此,两个计时器事件不能同时处理,一个回调将在另一个之后发生.
您仍然可以通过Web Workers在JavaScript中实现真正的并发.但是,Web worker不能与另一个Web worker或主线程共享任何对象.相反,Web工作者使用JSON序列化其状态对象,并与之交换消息postMessage.所以,你的情况仍然是不可能的.
但是,考虑另一种情况:
var shared = 100;
function workWithIt1(){
shared += 100;
}
function workWithIt2(){
shared = shared/2;
}
setTimeout(workWithIt1, 500);
setTimeout(workWithIt2, 500);
Run Code Online (Sandbox Code Playgroud)
将shared是150或者100,一旦两次超时都被解雇了?它可能会100,因为workWithIt1超时排在第一位.但是,我不会依赖这个事实,因为两个定时器具有相同的超时值500,并且定时器的实现可能是特定于浏览器的.您可能希望避免代码中的副作用.