Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在事件处理程序中读取和写入全局变量:并发性何时成为问题?_Javascript_Node.js_Events_Event Handling_Atomic - Fatal编程技术网

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

Javascript 在事件处理程序中读取和写入全局变量:并发性何时成为问题?,javascript,node.js,events,event-handling,atomic,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 =

我是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;
    setTimeout(() => {  
        var c = count;
        c++;
        count = c;
        console.log(c);  
    }, time);
});

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

console.log('Program Ended.');
//导入事件模块
var事件=要求(“事件”);
//事件发射器
var eventEmitter=new events.eventEmitter();
var max=1000;
var计数=0;
eventEmitter.on('event',()=>{
让时间=Math.trunc(Math.random()*1000)+1;
setTimeout(()=>{
var c=计数;
C++;
计数=c;
控制台日志(c);
},时间);
});
//火
for(设i=0;i
有没有原子性我不明白

但当我移动var创建和分配时,输出完全不同(最终结果为1)

//导入事件模块
var事件=要求(“事件”);
//事件发射器
var eventEmitter=new events.eventEmitter();
var max=1000;
var计数=0;
eventEmitter.on('event',()=>{
让时间=Math.trunc(Math.random()*1000)+1;
var c=计数;
setTimeout(()=>{
C++;
计数=c;
控制台日志(c);
},时间);
});
//火
for(设i=0;i
有什么建议吗?有什么读物吗


祝您愉快!

在代码启动时,eventemitter会一次性发出所有事件。因此,启动程序后会立即触发“事件”上的
。所有超时回调都是在所有事件处理程序注册完成后才调用的。将
控制台.log
放在“事件”中回调(不在
设置超时
回调中)并查看输出

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

var c = count;
settimeout
回调之外,因此回调将其递增为1

但在第一段代码中,在回调中读取代码段计数

var c = count; 

因此,每个回调都有更新的值。

来自Bergi提供的外部资源:

所有Javascript事件处理程序脚本都从一个主事件队列中处理。这意味着事件处理程序一次运行一个,一个运行到完成,然后下一个准备就绪的事件处理程序开始运行。因此,Javascript中不存在竞争条件。Javascript中的任何单个执行线程都将在e下一个开始

以及:

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


From

setTimeout
不是原子的。为什么在第一种情况下,它会成功计数到1000?如果它不是原子的,则类似于“读;读;写;写”应该发生,不是吗?
setTimeout
中的回调又是原子回调了。看一下,和。重点是,在安排超时和异步执行超时回调之间,其他任何事情都可能发生。哇,这正是我需要的!非常感谢。你好,Malice,谢谢你的回答!你是吗我是说,setTimeout中的匿名回调函数并不意味着不同事件处理之间存在任何并发性?我的意思是,为什么不可能有读;读;写;写;?代码是否总是这样执行:1/Java脚本执行并在列表中排队事件。2/称为“事件”的事件按顺序处理并排队“超时”事件。3/对每个事件队列执行超时回调事件发射不是异步调用(意味着它不会放弃事件循环),因此您的事件发射循环将一次性完成,您的
settimeout
调用在事件发射之间不会被调用。您可能希望将事件发射循环分成多个部分,例如,每个长度
max/4
,然后在回调中调用这些循环,以进行另一次
settimeout
,并进行随机计时。我猜每次都会遇到不同的结果。一个重要的收获是,您的事件发射循环从不放弃
事件循环(这是nodejs内部循环),因此它无法检查其中一个回调是否发生超时。。。
var c = count;