Подтвердить что ты не робот

Блокировка объекта?

Я очень новичок в Node.js, и я уверен, что есть простой ответ на этот вопрос, я просто не могу его найти: (

Я использую файловую систему для хранения "пакетов" (папки с расширениями состояния "mypackage.idle" ). Пользователи могут выполнять действия над ними, что приведет к тому, что статус переходит к чему-то вроде "qa" или "развертыванию", и т.д. Если сервер принимает много запросов и несколько запросов поступают для одного и того же пакета, как бы проверить статус, а затем выполнить действие, которое изменит статус, гарантируя, что другой запрос не изменил его до/во время акции?

поэтому в С# что-то вроде этого

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

Спасибо:)

4b9b3361

Ответ 1

Если checkStatus() и performAction() являются синхронными функциями, называемыми один за другим, то, как упоминалось ранее, их эксклюзия будет работать без вмешательства до завершения. Однако я подозреваю, что на самом деле обе эти функции асинхронны, и реалистичный случай их составления - это что-то вроде:

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

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

Приведенный выше код подвержен условиям гонки, так как когда doSomeIOStuff выполняется, вместо того, чтобы ждать его нового запроса.

Возможно, вы захотите проверить https://www.npmjs.com/package/rwlock библиотеку.

Ответ 2

Это немного вводит в заблуждение. Существует много языков script, которые, как предполагается, являются однопоточными, но при совместном использовании данных из одного источника это создает проблему. NodeJs может быть однопоточным, когда вы используете один запрос, но когда у вас есть несколько запросов, пытающихся получить доступ к тем же данным, он просто ведет себя, поскольку создает такую ​​же проблему, как если бы вы запускали многопоточный язык.

Об этом уже есть ответ: Блокировка на объекте?

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

Одна вещь, которую вы можете сделать, это заблокировать внешний объект, например, последовательность в базе данных, например Oracle или Redis.

http://redis.io/commands

Например, я использую кластер с node.js(у меня 4 ядра), и у меня есть функция node.js, и каждый раз, когда я ее запускаю, я увеличиваю переменную. Мне в основном нужно блокировать эту переменную, поэтому ни один из двух потоков не использует одно и то же значение этой переменной.

проверить это Как создать распределенный замок с помощью Redis?

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

Я думаю, вы можете работать с этой идеей, если знаете, что делаете.

Ответ 4

Если вы выполняете асинхронные вызовы с обратными вызовами, это означает, что несколько клиентов могут потенциально сделать одинаковые или связанные запросы и получать ответы в разных заказах. Это определенно случай, когда блокировка полезна. Вы не будете "блокировать поток" в традиционном смысле, а просто обеспечиваете асинхронные вызовы, а их обратные вызовы выполняются в предсказуемом порядке. Пакет async-lock выглядит так, как будто он обрабатывает этот сценарий.

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

Ответ 5

предупреждение, 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().

Ответ 6

Вам не нужно беспокоиться о синхронизации с Node.js, поскольку она однопоточная с циклом события. Это одно из преимуществ архитектуры, используемой Node.js.

Ничего не будет выполнено между checkStatus() и performAction().

Ответ 7

В node.js нет блокировок, потому что они вам не нужны. Там только один поток (цикл событий) и ваш код никогда не прерываются, если вы не выполняете асинхронное действие, такое как ввод-вывод. Следовательно, ваш код никогда не должен блокироваться. Вы не можете выполнять параллельный код.

Тем не менее, ваш код может выглядеть примерно так:

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() ни один другой поток не может прерывать, потому что нет ввода-вывода. Как только вы введете предложение if и установите qa_action_performed = true, никакой другой код не войдет в блок if, и поэтому perform_action() никогда не будет выполняться дважды, даже если perform_action() требует времени выполнения ввода-вывода.