以下是否有比赛条件? [英] Is there any race condition below?

查看:74
本文介绍了以下是否有比赛条件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的快递服务器中有以下代码(为简洁起见,已将其缩减).我有一个共同的目标,我要在三个不同的宁静终点中添加/修改/阅读.由于nodejs中的所有http请求都是异步的,因此我可以同时放置和获取请求 .因此,尽管发生了PUT,但可以说状态未更新 ,但是我的GET可能会得到较旧的响应?

I have below code in my express server (have cut it down for brevity). I have a common object which I'm adding/modifying/reading in three different restful end points. Since all http requests in nodejs are asynchronous, I could get both put and get request at the same time. So although PUT happened but lets say status is not updated, my GET could get a slightly stale response?

据我了解,我的测试表明这里没有比赛条件.因为更新results对象是同步操作,并且所有异步操作都应等待它.有人可以帮忙更好地解释一下这是否正确吗?

From what I understand, and my testing shows that there is no race condition here. Because updating results object is a synchronous operation and all async operations should wait for it. Can somebody help with a better explanation whether this is correct or not?

    var obj = {};
    const exec = require('child_process').exec;
    app.post('/foo', (req, res) => {
         var result = {};
         result.id = generateSomeRandomId();
         result.failed = 0;
         result.status = 'running'
         //execute some command and update result
         const child = exec('some command');
         child.stdout.on('data',  (data) => {
             //some logic
         });
         child.stderr.on('data',  (data) => {
             result.failed = result.failed + 1;
          });
         child.on('close',  (code, signal) => {
              if (signal !== null && signal !== undefined) {
                    result.status = 'cancelled';
              } else {
                    result.status = 'completed';
                    result.runtime = calculateRunTime();
                }
         });
         result.pid = child.pid;
         obj[result.id] = result; 
         res.send(result); 
    }   

    app.put('/foo/:id', (req, res) => {
         var result =  obj[req.params.id];
         if (result.status === 'running' && result.pid !== undefined) {
              kill(result.pid, 'SIGKILL');
              result.status = 'cancelled';
              result.runtime = calculateRunTime();
         }
         res.send(result);
    }   
    app.get('/foo/:id', (req, res) => {
         var result =  obj[req.params.id];
         res.send(result);
    }

推荐答案

您没有什么可称为比赛条件"的内容;这里存在不确定性因素,但实际上这不太可能.

You don't have anything I would call a "race condition"; there is an element of uncertainty at play here, but in practice it's not likely to matter.

您的post似乎启动了一个进程并返回ID,您的put取消了该进程,而您的get返回了该进程的当前状态.据此,我收集到,直到您的post完成并提供ID之前,您将永远无法get.

It looks like your post starts a process and returns the ID, your put cancels the process, and your get returns the current state of the process. From this I gather that you'll never be able to get until your post completes and provides the ID.

如果您在exec异步侦听器完成之前拨打并接收并返回get调用,您将获得最后的进行中状态-我认为这是设计使然.因此,这里唯一可能的冲突是您是否进行过put调用以暂停进程.

If you make a get call that is received and returned before your exec asynchronous listeners complete​, you'll get whatever the last in-progress state is - I assume that's by design. So the only possible conflict here is if you've made a put call to halt your process.

putget在与结果对象进行交互时都是同步的,因此,首先收到的是先完成的.您可以出于我们的目的忽略流程取消请求,因为它不会修改结果对象.无法保证将按照与客户发送的顺序相同的顺序来接收它们,这在您的情况下可能会或可能不会成为现实.

Both your put and your get are synchronous when it comes to interacting with your result object, so whichever one is received first is the one that will complete first. You can ignore the process cancellation request for our purposes because it doesn't modify the result object. There's no guarantee that they will be received in the same order they were sent by the client(s), that may or may not be a practical concern in your scenario.

相信(尽管这里的内存可能有问题),如果您使用cluster来处理不同进程中的请求,则将无法通过共享来传递数据无论如何还是对象,因此已经排除了这种可能性增加的任何复杂性.

I believe (though my memory may be faulty here), that if you were using cluster to handle requests in different processes, you wouldn't be able to pass data around via a shared object anyway, so any complexity added by that possibility is already ruled out.

因此,网络性能和可靠性上的差异是您唯一真正的通配符.服务器将按照请求进入的顺序处理请求,并为您提供预期的结果.如果只有一个客户端,则可以等到收到上一个请求的响应后再发送下一个,这可能会使性能降低到令人无法接受的程度,但会或多或少地提高其性能.否则,只需发送您的请求,而不必担心,只需使您的应用程序足够健壮以识别和评估您的应用即可.即使您已经取消了该流程,也要处理第二个取消请求.

So, variances in network performance and reliability are your only real wildcard here. The server will handle requests in the order they come in and give you the expected results. If you only have a single client, you can wait until you get the response from your previous request to send the next one, which would potentially slow down your performance unacceptably, but make it more or less bulletproof. Otherwise, just send off your requests and don't worry about it, just make your app robust enough to recognize & handle a 2nd cancellation request even if you've already cancelled the process.

这篇关于以下是否有比赛条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆