Can node.js code result in race conditions?

后端 未结 6 1814
小鲜肉
小鲜肉 2020-12-02 23:01

From what I read, race conditions occur when different threads try to change a shared variable, which can result in a value that\'s not possible with any serial order of exe

6条回答
  •  清歌不尽
    2020-12-02 23:59

    Yes. It can.

    Race condition in Nodejs is feasible when you use cluster module to initialise multiple workers.

    The case

    var cluster = require('cluster');
    var fs = require('fs');
    if(cluster.isMaster){
        for(var i=0;i<4;i++){
            cluster.fork();
        }
    }else{
        fs.watch('/path/to/file',function(){
            var anotherFile = '/path/to/anotherFile';
            fs.readFile(anotherFile,function(er,data){
                 if(er){
                     throw er;
                 }
                 data = +data+1;
                 fs.writeFile(anotherFile,data,function(er){
                     if(er){
                         throw er;
                     }
                     fs.readFile(anotherFile,function(er,newData){
                         if(er){
                             throw er;
                         }
                         console.log(newData); //newData is now undetermined
                     });
                 });
            });
        });
    }
    

    Whenever you change the watched file, 4 workers will execute the handler at the same time. This behaviour causes the undetermined newData.

    The solution

    if(cluster.isMaster){
        var lock = {};
        var timer = setInterval(function(){
            if(Object.keys(cluster.workers).length >= 4){
                return clearInterval(timer);
            }
            //note that this lock won't 100% work if workers are forked at the same time with loop.
            cluster.fork().on('message',function(id){
                 var isLocked = lock[id];
                 if(isLocked){
                     return console.log('This task has already been handled');
                 }
                 lock[id] = 1;
                 this.send('No one has done it yet');
            });
        },100);
    }else{
         process.on('message',function(){
            //only one worker can execute this task
            fs.watch('/path/to/file',function(){
                var anotherFile = '/path/to/anotherFile';
                fs.readFile(anotherFile,function(er,data){
                     if(er){
                         throw er;
                     }
                     data = +data+1;
                     fs.writeFile(anotherFile,data,function(er){
                         if(er){
                            throw er;
                         }
                         fs.readFile(anotherFile,function(er,newData){
                             if(er){
                                 throw er;
                             }
                             console.log(newData); //newData is now determined
                         });
                     });
                });
            });
         });
         //ask the master for permission
         process.send('watch');
    }
    

提交回复
热议问题