Javascript线程处理和竞争条件

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如何处理其线程,何时在线程之间切换,是否有内置方法,可用于处理竞争条件?

nos*_*tio 6

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)

shared150或者100,一旦两次超时都被解雇了?它可能会100,因为workWithIt1超时排在第一位.但是,我不会依赖这个事实,因为两个定时器具有相同的超时值500,并且定时器的实现可能是特定于浏览器的.您可能希望避免代码中的副作用.