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

Семафор javascript/test-and-set/lock?

Есть ли такая вещь, как атомный тест-набор, семафор или блокировка в Javascript?

У меня есть javascript, вызывающий фоновые процессы async через собственный протокол (фоновый процесс буквально запускается в отдельном процессе, не связанный с браузером). Я верю, что я столкнулся с гоночным состоянием; фоновый процесс возвращается между моим тестом и моим набором, закручивая вещи на стороне javascript. Мне нужна тестовая операция, чтобы сделать ее настоящим семафором.

Вот код javascript, который пытается обнаружить фоновые процессы и поставить их в очередь:

Call = function () {

var isRunning = true,
    queue = [];

return  {
    // myPublicProperty: "something",

    call: function (method) {
            if (isRunning) {
                console.log("Busy, pushing " + method);
                queue.push(method);
            } else {
                isRunning = true;
                objccall(method);
            }
        },

        done: function() {
            isRunning = false;
            if (queue.length > 0) {
                Call.call(queue.shift());
            }
        }
    };
}();

Звонок - это синглтон, который реализует очередность; любой, кто хочет вызвать внешний процесс, вызывает Call.call( "что-то" ).

Любые идеи?

4b9b3361

Ответ 1

В JavaScript нет семантики блокировки, поскольку JS не является многопоточным языком. Несколько потоков могут работать только в совершенно разных контекстах - например. Рабочие потоки HTML5 или такие вещи, как несколько экземпляров контекстного объекта JavaScriptCore API (я полагаю, что SpiderMonkey имеет аналогичную концепцию). Они не могут иметь разделяемое состояние, поэтому по существу все выполнение является атомарным.

Хорошо, поскольку теперь вы предоставили часть своего кода, я предполагаю, что у вас есть что-то похожее на:

External Process:
<JSObject>.isRunning = true;
doSomething()
<JSObject>.done()

Или некоторые из них (с использованием соответствующих API). В этом случае я ожидал бы, что JS-движок блокируется, если JS будет выполняться в контексте вашего js-объекта (что будет делать JavaScriptCore), в противном случае вам, вероятно, понадобится установить ручную блокировку вокруг выполнения js.

Какой движок вы используете, чтобы сделать все это? Я спрашиваю, потому что, основываясь на вашем описании, похоже, что вы устанавливаете флаг из вторичного потока с языка, отличного от JS, с использованием C/С++ API, предоставляемого этим языком, и большинство JS-модулей предполагают, что любое манипулирование состояниями, созданное с помощью API будет происходить в одном потоке, обычно в том же потоке, что и все выполнение.

Ответ 2

Быстрый поиск Google для "javascript mutex" вернул эту статью (Реализация взаимного исключения в JavaScript).

Ответ 3

Возможно, вы могли бы реализовать базовый целочисленный семафор, просто добавьте переменную в DOM и заблокируйте/разблокируйте ее и убедитесь, что ваши функции продолжают ее проверять, иначе тайм-аут =)

Если вы используете фреймворк, такой как Mootools, вы можете попытаться обработать поток приложения с такими событиями, как onComplete и т.д.

Ответ 4

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

var semaphore=[];

function myFunc(arg){
   var dfd;
   $.when(semaphore[table]).done(
      function(){
            dfd=myFuncInner(arg);
      }
      );
return dfd;
}

function myFuncInner(table){
semaphore[arg] = new $.Deferred();
... 
somethingasynchronous({
    semaphore[arg].resolve();
});

return  semaphore[arg];
}

Ответ 5

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

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

Хотя было бы неплохо иметь возможность отменить кнопку fadeout и просто установить свой стиль на "display: none", как только запрос Ajax будет завершен, это невозможно в jQuery. Кроме того, решение может использовать события для синхронизации двух одновременных действий, но это по существу является излишним для простой проблемы.

Низкотехнологичное решение - опрос блокировки, и когда завершение fadeout завершается, оно разблокируется, но сообщение "server done" НЕ отображается до тех пор, пока не будет выполнен обратный вызов успеха, заданный параметром $.post.

var gl_lock;
var gl_selfID;

function poll_lock(message) {
     if (gl_lock === 0) {
          $('#output').text(message).fadeIn(200);
          window.clearInterval(gl_selfID);
     }
 } // end of poll_lock

 function worker() {

     // no one gets in or out
     gl_lock = 1;

     $.post(..., data,function() { 
           gl_selfID = window.setInterval(poll_lock, 40, data.message);
      }, "json");

     // end of fadeout unlock the semaphore
     $('#submit-button').fadeOut(400, function() { gl_lock = 0; });

  } // end of worker

Наконец, я думаю, что это более подробный ответ, в соответствии с ранее предложенными в этом обсуждении perrohunter.

Ответ 6

Я не совсем уверен, что вопрос задает именно так, но посмотрите здесь мой объект семафора: https://github.com/agamemnus/semaphore.js.