这个代码可以在socket io中引起竞争条件吗?

cgo*_*gon 4 node.js socket.io

我是节点js和socket io的新手.此代码是否可以导致计数器变量的竞争条件.我应该使用锁定库来安全地更新计数器变量.

"use strict";

module.exports = function (opts) {
    var module = {};

    var io = opts.io;

    var counter = 0;

    io.on('connection', function (socket) {

        socket.on("inc", function (msg) {
            counter += 1;
        });

        socket.on("dec" , function (msg) {
            counter -= 1;
        });

    });


    return module;
};
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 7

不,这里没有竞争条件.node.js中的Javascript是单线程和事件驱动的,因此一次只执行一个socket.io事件处理程序.这是来自单线程模型的良好编程简化之一.它运行给定的执行线程,然后才会从事件队列中获取下一个事件并运行它.

希望您确实意识到counter所有socket.io连接都访问相同的变量.虽然这不是竞争条件,但这意味着只有一个counter所有socket.io连接都能够修改.

如果你想要一个每连接计数器(每个连接的separeate计数器),那么你可以counterio.on('connection', ....)处理程序中定义变量.


您必须在node.js中注意的竞争条件是当您进行异步调用然后在异步回调中继续其余的编码逻辑时.当异步操作正在进行时,其他node.js代码可以运行,并且可以更改您可能正在使用的可公开访问的变量.在您的counter示例中情况并非如此,但它确实发生在许多其他类型的node.js编程中.

例如,这可能是一个问题:

var flag = false;

function doSomething() {
    // set flag indicating we are in a fs.readFile() operation
    flag = true;
    fs.readFile("somefile.txt", function(err, data) {
        // do something with data

        // clear flag
        flag = false;
    });
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们在调用之后立即fs.readFile()将控制权返回给node.js. 当时可以免费运行其他操作.如果另一个操作也可以运行此代码,那么它将会破坏价值,flag并且我们会遇到并发问题.

因此,您必须知道,无论何时进行异步操作,然后其余逻辑继续在异步操作的回调中,其他代码都可以运行,并且此时可以访问任何共享变量.您需要制作共享数据的本地副本,或者需要为共享数据提供适当的保护.

在这种特殊情况下,标志可以递增和递减,而不是简单地设置为true或者false它可能用于跟踪该文件当前是否被读取的所需目的.