Question Sémaphore Javascript / test-and-set / lock


Existe-t-il un test et un ensemble atomiques, un sémaphore ou un verrou dans Javascript?

J'ai javascript appelant des processus d'arrière-plan asynchrones via un protocole personnalisé (le processus d'arrière-plan s'exécute littéralement dans un processus distinct, sans rapport avec le navigateur). Je crois que je cours dans une condition de course; le processus d'arrière-plan revient entre mon test et mon set, en vissant le côté javascript. J'ai besoin d'une opération de test et de configuration pour en faire un véritable sémaphore.

Voici le code javascript qui tente de détecter les processus en arrière-plan et de les mettre en file d'attente:

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 est un singleton qui implémente la file d'attente; Toute personne souhaitant appeler un processus externe appelle Call.call ("quelque chose").

Des idées?


44
2018-02-17 00:51


origine


Réponses:


JavaScript n'a pas de sémantique de verrouillage car JS n'est pas un langage multithread. Plusieurs threads ne peuvent fonctionner simultanément que dans des contextes complètement distincts, par exemple. HTML5 Worker threads, ou dans des choses comme plusieurs instances de l'objet de contexte de l'API JavaScriptCore (je suppose que SpiderMonkey a un concept similaire). Ils ne peuvent pas avoir d’état partagé, donc, en substance, toute exécution est atomique.

Bon, comme vous avez maintenant fourni une partie de votre code, je suppose que vous avez quelque chose qui ressemble à:

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

Ou certains de ceux-ci (en utilisant les API appropriées). Dans ce cas, je m'attendrais à ce que le moteur JS se bloque si JS s'exécute dans le contexte de votre objet js (ce que ferait JavaScriptCore), à ​​défaut de devoir mettre en place un verrou manuel autour de l'exécution de js.

Quel moteur utilisez-vous pour faire tout cela? Je vous le demande parce que selon votre description, il semble que vous définissiez un indicateur à partir d’un thread secondaire à partir d’un langage non-JS utilisant l’API C / C ++ fournie par ce langage, et la plupart des moteurs JS se produira sur un seul thread, généralement le même thread que toute l'exécution se produit.


18
2018-02-17 01:19



Peut-être pourriez-vous implémenter un sémaphore d'entier de base, ajouter simplement la variable dans le DOM et la verrouiller / déverrouiller pour vous assurer que vos fonctions continuent de le vérifier, sinon timeout them =)

Si vous utilisez un framework tel que Mootools, vous pouvez essayer de gérer le flux de l'application avec des événements tels que onComplete, etc.


2
2018-02-17 01:16



Tout d’abord, même si javaScript est un thread unique, il n’est PAS vrai qu’aucune application javaScript n’a besoin d’un mécanisme de sérialisation.

Un exemple simple est celui où un bouton d'envoi doit disparaître pendant un laps de temps défini pendant lequel une requête Ajax sur un serveur fonctionne. Lorsque la requête asynchrone Ajax se termine avec succès, un message doit apparaître où se trouvait le bouton.

Bien qu'il soit intéressant de pouvoir annuler le fadeout du bouton et simplement définir son style sur "display: none", dès que la requête Ajax se termine, ce n'est pas possible dans jQuery. En outre, une solution pourrait utiliser les événements pour synchroniser les deux activités simultanées, mais cela est essentiellement exagéré pour un problème simple.

Une solution de basse technologie consiste à interroger un verrou et à la fin du fadeout, il est déverrouillé, mais le message "server done" n'est PAS affiché tant que le rappel de succès, défini par $ .post, n'est pas exécuté.

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

Enfin, je pense que cette réponse est plus détaillée, selon les lignes suggérées précédemment par Perrohunter dans cette discussion.


1
2017-10-04 00:24



J'ai des trucs ajax qui remplissent des listes sélectionnées, il fallait que ce soit verrouillé alors j'ai fait quelque chose comme ça. Je pense que vous pourriez probablement le faire plus simplement en utilisant des différés et des tuyaux ou quelque chose.

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];
}

0
2018-06-08 22:33



Je ne suis pas vraiment sûr de ce que la question pose exactement, mais regardez mon objet sémaphore ici: https://github.com/agamemnus/semaphore.js.


0
2018-01-15 02:31