Can this code cause a race condition in socket io?

2019-05-06 15:42发布

I am very new to node js and socket io. Can this code lead to a race condition on counter variable. Should I use a locking library for safely updating the counter variable.

"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;
};

2条回答
手持菜刀,她持情操
2楼-- · 2019-05-06 16:34

No, there is no race condition here. Javascript in node.js is single threaded and event driven so only one socket.io event handler is ever executing at a time. This is one of the nice programming simplifications that come from the single threaded model. It runs a given thread of execution to completion and then and only then does it grab the next event from the event queue and run it.

Hopefully you do realize that the same counter variable is accessed by all socket.io connections. While this isn't a race condition, it means that there's only one counter that all socket.io connections are capable of modifying.

If you wanted a per-connection counter (separeate counter for each connection), then you could define the counter variable inside the io.on('connection', ....) handler.


The race conditions you do have to watch out for in node.js are when you make an async call and then continue the rest of your coding logic in the async callback. While the async operation is underway, other node.js code can run and can change publicly accessible variables you may be using. That is not the case in your counter example, but it does occur with lots of other types of node.js programming.

For example, this could be an issue:

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;
    });
}

In this case, immediately after we call fs.readFile(), we are returning control back to the node.js. It is free at that time to run other operations. If another operation could also run this code, then it will tromp on the value of flag and we'd have a concurrency issue.

So, you have to be aware that anytime you make an async operation and then the rest of your logic continues in the callback for the async operation that other code can run and any shared variables can be accessed at that time. You either need to make a local copy of shared data or you need to provide appropriate protections for shared data.

In this particular case, the flag could be incremented and decremented rather than simply set to true or false and it would probably serve the desired purpose of keeping track of whether this file is current being read or not.

查看更多
干净又极端
3楼-- · 2019-05-06 16:34

Shorter answer:

"Race condition" is when you execute a series of ordered asynchronous functions and because of their async nature they won't finish processing in their original order.

In your code, you are executing a series of ordered synchronous process (increasing or decreasing the counter), So they finish instantly after they start, resulting in ordered output. So no racing here!

查看更多
登录 后发表回答