我对Node.js很新,我确信这个答案很简单,我找不到它:(
我正在使用文件系统来保存'packages'(状态扩展名为'mypackage.idle'的文件夹)用户可以对这些文件执行操作,这会导致状态变为“qa”或“部署”等等...如果服务器正在接受大量请求并且多个请求进入同一个包,我将如何检查状态然后执行操作,这将改变状态,保证另一个请求在之前没有改变它/在行动期间发生了什么?
所以在c#这样的事情
lock (someLock) { checkStatus(); performAction(); }
谢谢:)
答案 0 :(得分:7)
如果checkStatus()和performAction()是一个接一个地调用的同步函数,那么正如前面提到的那些:它们的exectution将不间断地运行直到完成。 但是,我怀疑实际上这两个函数都是异步的,组成它们的现实情况如下:
function checkStatus(callback){
doSomeIOStuff(function(something){
callback(something == ok);
});
}
checkStatus(function(status){
if(status == true){
performAction();
}
});
上述代码受竞争条件限制,因为当doSomeIOStuff正在执行而不是等待它时,可以提供新的请求。
您可能需要查看https://www.npmjs.com/package/rwlock库。
答案 1 :(得分:1)
这有点误导。有许多脚本语言被认为是单线程的,但是当从同一源共享数据时,这会产生问题。当您运行单个请求时,NodeJ可能是单线程的,但是当您有多个请求尝试访问相同的数据时,它的行为与它创建的问题类似于运行多线程语言一样。
这里已经有了一个答案: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
答案 2 :(得分:1)
您可以做的一件事就是锁定外部对象,例如Oracle或Redis等数据库中的序列。
例如,我正在使用带有node.js的集群(我有4个核心),并且我有一个node.js函数,每次运行它时,我都会增加一个变量。我基本上需要锁定该变量,因此没有两个线程使用该变量的相同值。
查看How to create a distributed lock with Redis?
和https://engineering.gosquared.com/distributed-locks-using-redis
如果你知道自己在做什么,我认为你可以运用这个想法。
答案 3 :(得分:1)
如果您使用回调进行异步调用,这意味着多个客户端可能会生成相同或相关的请求,并以不同的顺序接收响应。这肯定是锁定有用的情况。你不会在传统意义上“锁定线程”,而只是确保异步调用,并且它们的回调是以可预测的顺序进行的。 async-lock包看起来像处理这种情况。
答案 4 :(得分:-2)
警告,如果添加日志条目,则node.js会更改语义,因为日志记录是IO绑定的。
如果您从
更改qa_action_performed = false
function handle_request() {
if (check_status() == STATUS_QA && !qa_action_performed) {
qa_action_performed = true
perform_action()
}
}
到
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()
}
}
多个线程可以执行perform_action()。
答案 5 :(得分:-4)
您不必担心与Node.js的同步,因为它是单线程的事件循环。这是Node.js使用的体系结构的优势之一。
checkStatus()
和performAction()
之间不执行任何操作。
答案 6 :(得分:-7)
node.js中没有锁 - 因为您不需要它们。只有一个线程(事件循环),除非您执行I / O之类的异步操作,否则您的代码永远不会中断。因此,您的代码永远不会阻止。你不能执行任何并行代码。
那就是说,你的代码看起来像这样:
qa_action_performed = false
function handle_request() {
if (check_status() == STATUS_QA && !qa_action_performed) {
qa_action_performed = true
perform_action()
}
}
在check_status()和perform_action()之间没有其他线程可以中断,因为没有I / O.只要输入if子句并设置qa_action_performed = true,就不会有其他代码进入if块,因此perform_action()永远不会执行两次,即使perform_action()需要时间执行I / O.