锁定一个物体?

时间:2011-02-28 18:04:23

标签: node.js locking

我对Node.js很新,我确信这个答案很简单,我找不到它:(

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

所以在c#这样的事情

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

谢谢:)

7 个答案:

答案 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等数据库中的序列。

http://redis.io/commands

例如,我正在使用带有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包看起来像处理这种情况。

https://www.npmjs.com/package/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.