Node.js 锁定一个对象?

Node.js 锁定一个对象?,node.js,locking,Node.js,Locking,我对Node.js非常陌生,我相信有一个简单的答案,我就是找不到:( 我正在使用文件系统来保存“包”(状态扩展名为“mypackage.idle”的文件夹)用户可以对这些文件执行操作,这将导致状态变为“qa”或“deploying”等。如果服务器正在接受大量请求,并且同一个包中有多个请求,我如何检查状态,然后执行操作,从而更改状态,确保另一个请求不会更改它在行动发生之前/期间 所以在c#中,类似这样的东西 lock (someLock) { checkStatus(); performActio

我对Node.js非常陌生,我相信有一个简单的答案,我就是找不到:(

我正在使用文件系统来保存“包”(状态扩展名为“mypackage.idle”的文件夹)用户可以对这些文件执行操作,这将导致状态变为“qa”或“deploying”等。如果服务器正在接受大量请求,并且同一个包中有多个请求,我如何检查状态,然后执行操作,从而更改状态,确保另一个请求不会更改它在行动发生之前/期间

所以在c#中,类似这样的东西

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

谢谢:)

您不必担心与Node.js的同步,因为它是单线程的,带有事件循环。这是Node.js使用的体系结构的优点之一


checkStatus()
performAction()
之间不会执行任何操作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需要时间。

这有点误导。有许多脚本语言被认为是单线程的,但当共享来自同一源的数据时,这会产生问题。当您运行单个请求时,NodeJ可能是单线程的,但是当您有多个请求试图访问相同的数据时,它的行为就像您运行多线程语言一样,会产生类似的问题

关于这一点,这里已经有了答案:


警告,如果添加日志条目,node.js将更改语义,因为日志记录是IO绑定的

如果你从

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

多个线程可以执行perform_action()。

如果checkStatus()和performAction()是一个接一个调用的同步函数,那么正如前面提到的其他函数一样:它们的执行将不间断地运行,直到完成。 然而,我怀疑在现实中,这两个函数都是异步的,组合它们的实际情况如下:

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

checkStatus(function(status){
  if(status == true){
    performAction();
  }
});
上面的代码受竞争条件的约束,因为当doSomeIOStuff正在执行而不是等待时,新的请求可以被服务


您可能需要检查库。

您可以做的一件事是锁定外部对象,例如,数据库(如Oracle或Redis)中的序列

例如,我使用带有node.js的集群(我有4个核心),我有一个node.js函数,每次运行它时,我都会增加一个变量。我基本上需要锁定该变量,这样就不会有两个线程使用该变量的相同值

看看这个

还有这个


如果你知道自己在做什么,我想你可以用这个想法来运行。

如果你使用回调进行异步调用,这意味着多个客户端可能会发出相同或相关的请求,并以不同的顺序接收响应。在这种情况下,锁定肯定是有用的。您不会在传统意义上“锁定线程”,而只是确保异步调用,并且它们的回调是按可预测的顺序进行的。异步锁包看起来可以处理这种情况


不错!非常感谢。因此,即使http.createServer每秒可以异步处理数百个请求,但一次只能有一个请求进入上面的“handle_request”函数?正如上面的代码所示,是的。如果您在check_status()中有异步I/O,例如,因为您需要访问数据库或文件系统,您将使用回调,如check_status(函数(结果){If(结果==status_QA&&…})。在这种情况下,多个请求可以输入handle_request(),但在执行了!qa_action_之后,您仍然可以避免多次执行perform_action()。我发现Node.js中的“无并行代码执行”这一模因令人困惑。如果您有两个任务(T1和T2)每一个都需要,比如说,10个异步回调链接在一起,然后T2的一些回调将在T1等待异步操作完成时执行。这不是T1和T2以“并行”方式执行吗?如果T1和T2有一些共享的、不可重入的资源,他们是否不需要锁定该资源以确保这两个任务不会损坏它?-1表示
,因为您不应该需要它们
。您绝对需要它们(如@mehaase所述)除非你的应用程序仅仅是一个计算器,-1同样。在异步IO操作在执行时可以互相中断的环境中,你怎么可能不需要访问信号量?(参见@mehaase和@freakish)提供的链接是递归练习。答案不明确。如果是“数据”这指的是文件系统、数据库和外部进程,那么锁定仍然是一个问题。如果这指的是进程内数据结构,那么锁定就不是问题,正如其他答案所述。@RichardMarr当然是。如果你有一个函数
T
,它链接了10个改变共享数据结构的异步操作ata结构(都在Node.js进程中),那么如果连续运行两次
T
,会发生什么?这是一个竞争条件。-1所有这些争论,甚至没有人提到@lac_dev用一个用剪辑编写的示例回答了Node.js问题:)WTF@Basezen这场争论可能是我最不光彩的时刻,很明显,这是沟通的中断。两个人以最不利的角度解释对方的答案,并试图纠正它们
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()
  }
}
function checkStatus(callback){
  doSomeIOStuff(function(something){
    callback(something == ok);
  });
}

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