Locking on an object?

笑着哭i 提交于 2019-12-18 03:15:22

问题


I'm very new to Node.js and I'm sure there's an easy answer to this, I just can't find it :(

I'm using the filesystem to hold 'packages' (folders with a status extensions 'mypackage.idle') Users can perform actions on these which would cause the status to go to something like 'qa', or 'deploying' etc... If the server is accepting lots of requests and multiple requests come in for the same package how would I check the status and then perform an action, which would change the status, guaranteeing that another request didn't alter it before/during the action took place?

so in c# something like this

lock (someLock) { checkStatus(); performAction(); }

Thanks :)


回答1:


If checkStatus() and performAction() are synchronous functions called one after another, then as others mentioned earlier: their exectution will run uninterupted till completion. However, I suspect that in reality both of these functions are asynchoronous, and the realistic case of composing them is something like:

function checkStatus(callback){
  doSomeIOStuff(function(something){
    callback(something == ok);
  });
}

checkStatus(function(status){
  if(status == true){
    performAction();
  }
});

The above code is subject to race conditions, as when doSomeIOStuff is being perfomed instead of waiting for it new request can be served.

You may want to check https://www.npmjs.com/package/rwlock library.




回答2:


This is a bit misleading. There are many script languages that are suppose to be single threaded, but when sharing data from the same source this creates a problem. NodeJs might be single threaded when you are running a single request, but when you have multiple requests trying to access the same data, it just behaves as it creates kind of the same problem as if you were running a multithreaded language.

There is already an answer about this here : Locking on an object?

WATCH sentinel_key
GET value_of_interest
if (value_of_interest = FULL)
    MULTI
    SET sentinel_key = foo
    EXEC
    if (EXEC returned 1, i.e. succeeded)
        do_something();
    else
        do_nothing();
else
    UNWATCH



回答3:


One thing you can do is lock on an external object, for instance, a sequence in a database such as Oracle or Redis.

http://redis.io/commands

For example, I am using cluster with node.js (I have 4 cores) and I have a node.js function and each time I run through it, I increment a variable. I basically need to lock on that variable so no two threads use the same value of that variable.

check this out How to create a distributed lock with Redis?

and this https://engineering.gosquared.com/distributed-locks-using-redis

I think you can run with this idea if you know what you are doing.




回答4:


If you are making asynchronous calls with callbacks, this means multiple clients could potentially make the same, or related requests, and receive responses in different orders. This is definitely a case where locking is useful. You won't be 'locking a thread' in the traditional sense, but merely ensuring asynchronous calls, and their callbacks are made in a predictable order. The async-lock package looks like it handles this scenario.

https://www.npmjs.com/package/async-lock




回答5:


warning, node.js change semantic if you add a log entry beucause logging is IO bound.

if you change from

qa_action_performed = false
function handle_request() {
  if (check_status() == STATUS_QA && !qa_action_performed) {
    qa_action_performed = true
    perform_action()
  }
}

to

qa_action_performed = false
function handle_request() {
  if (check_status() == STATUS_QA && !qa_action_performed) {
    console.log("my log stuff");
    qa_action_performed = true
    perform_action()
  }
}

more than one thread can execute perform_action().




回答6:


You don't have to worry about synchronization with Node.js since it's single threaded with an event loop. This is one of the advantage of the architecture that Node.js use.

Nothing will be executed between checkStatus() and performAction().




回答7:


There are no locks in node.js -- because you shouldn't need them. There's only one thread (the event loop) and your code is never interrupted unless you perform an asynchronous action like I/O. Hence your code should never block. You can't do any parallel code execution.

That said, your code could look something like this:

qa_action_performed = false
function handle_request() {
  if (check_status() == STATUS_QA && !qa_action_performed) {
    qa_action_performed = true
    perform_action()
  }
}

Between check_status() and perform_action() no other thread can interrupt because there is no I/O. As soon as you enter the if clause and set qa_action_performed = true, no other code will enter the if block and hence perform_action() is never executed twice, even if perform_action() takes time performing I/O.



来源:https://stackoverflow.com/questions/5145749/locking-on-an-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!