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

Node.js и мьютексы

Мне интересно, нужны ли мьютексы/блокировки для доступа к данным в Node.js. Например, скажем, я создал простой сервер. Сервер предоставляет несколько методов протокола для добавления и удаления из внутреннего массива. Нужно ли мне защищать внутренний массив с помощью некоторого типа мьютекса?

Я понимаю, что Javascript (и, следовательно, Node.js) является однопоточным. Я просто не понимаю, как обрабатываются события. Прерывают ли события? Если это так, мое приложение может быть в середине чтения массива, прервать его, чтобы запустить обратный вызов события, который изменяет массив, а затем продолжить обработку массива, который теперь был изменен обратным вызовом события.

4b9b3361

Ответ 1

Мне интересно, требуются ли мьютексы/блокировки для доступа к данным в Node.js.

Нету! События обрабатываются в тот момент, когда нет другого кода для запуска, это означает, что не будет никаких конфликтов, поскольку только текущий запущенный код имеет доступ к этому внутреннему массиву. Как побочный эффект однопоточного узла, длинные вычисления будут блокировать все остальные события, пока вычисления не будут завершены.

Я понимаю, что Javascript (и, следовательно, Node.js) является однопоточным. Мне просто не ясно, как обрабатываются события. Прерываются ли события?

Нет, события не прерываются. Например, если вы while(true){} в свой код while(true){}, это остановит выполнение любого другого кода, потому что всегда есть другая итерация цикла, который нужно запустить.

Если у вас длительные вычисления, рекомендуется использовать process.nextTick, так как это позволит запускать его, когда ничего не запущено (я не совсем уверен в этом: приведенный ниже пример показывает, что я, вероятно, прямо об этом работает бесперебойно, наверное).

Если у вас есть другие вопросы, не стесняйтесь заходить в # node.js и задавать вопросы. Кроме того, я попросил пару человек посмотреть на это и убедиться, что я не совсем неправ;)

var count = 0;

var numIterations = 100;
while(numIterations--) {
  process.nextTick(function() {
    count = count + 1;
  });
}

setTimeout(function() {

  console.log(count);

}, 2);

//
//=> 100
//

Благодаря AAA_awright из # node.js :)

Ответ 2

Замки и мьютексы действительно необходимы иногда, даже если Node.js является однопоточным.

Предположим, у вас есть два файла, которые должны иметь один и тот же контент и не иметь одного и того же содержимого, как несогласованное состояние. Теперь предположим, что вам нужно изменить их, не блокируя сервер. Если вы это сделаете:

fs.writeFile('file1', 'content', function (error) {
    if (error) {
        // ...
    } else {
        fs.writeFile('file2', 'content', function (error) {
            if (error) {
                // ...
            } else {
                // ready to continue
            }
        });
    }
});

вы попадаете в несогласованное состояние между двумя вызовами, когда другая функция в том же script может считывать два файла.

Модуль rwlock идеально подходит для обработки этих случаев.

Ответ 3

Я искал решение для мьютексов node. Иногда необходимы взаимные блокировки - вы можете запускать несколько экземпляров вашего приложения node и, возможно, захотите заверить, что только один из них выполняет какую-то определенную вещь. Все решения, которые я мог найти, были либо не перекрестными, либо зависящими от redis.

Итак, я сделал свое собственное решение, используя блокировки файлов: https://github.com/Perennials/mutex-node

Ответ 4

Мьютексы определенно необходимы для многих реализаций на стороне сервера. Рассмотрим класс, в котором вам необходимо поддерживать синхронность асинхронного выполнения путем построения цепочки обещаний.

let _ = new WeakMap();
class Foobar {
  constructor() {
    _.set(this, { pc : Promise.resolve() } );
  }
  doSomething(x) {
    return new Promise( (resolve,reject) => {
      _.get(this).pc = _.get(this).pc.then( () => {
        y = some value gotten asynchronously
        resolve(y);
      })
    })
  }
}

Как вы можете быть уверены в том, что обещание не будет зависеть от состояния гонки? Это разочаровывает, что этот узел не сделал мьютексы нативными, поскольку javascript настолько асинхронен по своей природе, и перенос сторонних модулей в пространство процесса всегда представляет угрозу безопасности.