在事件处理程序中读取和写入全局变量:并发何时成为问题?

时间:2017-08-21 14:19:43

标签: javascript node.js events event-handling atomic

我是Node.JS的新手,我开始阅读有关Node.js事件处理和并发的几个主题。

以下代码触发1000次事件,通过递增全局变量来处理。第一位代码成功计数到1000,但第二位甚至没有增加到2.是否有任何原子性我无法获得?

我仍然想知道为什么下面的代码会提供一致的输出(它成功计算到1000而没有任何并发​​:

// Import events module
var events = require('events');

// Event emitter
var eventEmitter = new events.EventEmitter();

var max = 1000;

var count = 0;

eventEmitter.on('event', () => {
    let time = Math.trunc(Math.random() * 1000) +1;
    var c = count;
    setTimeout(() => {  

        c++;
        count = c;
        console.log(c);  
    }, time);
});

// Fire
for (let i = 0; i < max; i++) {
    eventEmitter.emit('event');
}

console.log('Program Ended.');

我有什么原子性不能得到吗?

但是当我移动var创建&amp;分配,输出完全不同(最终结果为1)。

{{1}}

有什么建议吗?有读物吗?

度过美好的一天!

2 个答案:

答案 0 :(得分:1)

来自Bergi提供的外部资源:

  

所有Javascript事件处理程序脚本都是从一个主事件队列处理的。这意味着事件处理程序一次运行一个,一个运行直到完成,然后下一个准备开始运行。因此,Javascript中没有竞争条件。 javascript中的任何单独执行线程将在下一个启动之前运行完成。

来自this

并且:

  

在触发下一个事件之前,一个事件将运行完成。因此,如果在第一次处理仍然处理时发生第二次单击,则第二次单击将排队,并且在处理完第一次的代码完成之前不会运行。

来自that

答案 1 :(得分:0)

当代码启动时,eventemitter最初一次性发出所有事件。因此在启动程序后立即触发on 'event'。在完成所有事件处理程序注册后,所有超时回调都是。在console.log回调中放入event(不在settimeout回调中)并查看输出。

在第二个代码段中,所有settimeout回调都会捕获count = 0,因为

var c = count;

settimeout回调之外,因此回调将其递增为1.

但是在第一个代码片段计数是在回调中读取的

var c = count; 

所以每个回调都有更新的值。