javascript critical sections or semaphore problem

2019-07-04 05:04发布

问题:

function myobj(){
  var gup=this;
  this.lastindex=-1;
  this.criticalSectionInTimer=0;
  this.updateTimer;

  this.start = function(l){
      if((typeof this.updateTimer)=="number"){
        clearInterval ( this.updateTimer );
      }
      this.updateTimer=setInterval(function() {gup.getMessages();} , 30);
    }

    this.stop= function(){
      if((typeof this.updateTimer)=="number"){
        clearInterval ( this.updateTimer );
      }  
    }

  this.addUpdate(i){
    //some code
  }

  this.rrrrnr=0;

  this.getMessages = function (){
    if(this.criticalSection==0){
       this.criticalSection=1;
      this.rrrrnr++;
      console.log("in critical section"+this.rrrrnr);
         var url="getmessages.php?lastindex="+this.lastindex;
         $.getJSON(url,
             function(data){
              gup.lastindex=data.lastindex;
              $.each(data.updates, function(i,item){
                gup.addUpdate(item);
              });
           }
         );
       console.log("out critical section"+this.rrrrnr);
       this.criticalSection=0;
    }
  }

}

var m= new myobj();
myobj.start();

I have the code from above. I have a main loop which makes updates at a given time interval. The problem is i have realized that it is getting in the "critical section" which I have delimited by the variable this.criticalSection .

From firebug i get the messages "in critical section" + index and "out critical section" +index in the right order but the ajax request is still being processed. But I get request with the same index and i really don't know where to look for the problem.

Are there any buildin features for semaphores or critical sections in javascript?

回答1:

There aren't semaphores or critical sections because JavaScript is single-threaded. The ajax call you make is asynchronous, so it kicks off the request and then happily keeps going and leaving your critical section. As others have mentioned, a simple solution is to make the request synchronous, but this defeats the purpose of ajax.

Looking at your code, it seems like you are trying to get updates at regular intervals. If this is the case, why not schedule the next update in the callback of the ajax request?

this.getMessages = function (){
    var url="getmessages.php?lastindex="+this.lastindex;
    $.getJSON(url,
        function(data){
            gup.lastindex=data.lastindex;
            $.each(data.updates, function(i,item){
                gup.addUpdate(item);
            });
  gup.updateTimer=setTimeout(gup.getMessages, 30);
        }
    );

}

This would remove the need for semaphores, and is more in line with the event-driven nature of JavaScript. The downside is the updates are not done at exact intervals. Also, 30 milliseconds seems an extremely short interval.



回答2:

jQuery send AJAX Async by default. Insted of doing getJSON try:

$.ajax({
  dataType: 'json',
  url:  url,
  type: 'GET',
  async: false,
  success: function(data){
              gup.lastindex=data.lastindex;
              $.each(data.updates, function(i,item){
                gup.addUpdate(item);
              });
});


回答3:

The proble is fairly simple.

You are using AJAX, which, by definition, is asynchronous. That means, you execute $.getJSON, and the js will continue and exit the critical section while the request is being processed. Therefore, several calls to getMessages can be performed before the first requests completes.

It seems that you intend such a getJSON call NOT not be async, and be blocked within the critical section until it ends. To do so, you must set the async property to false, something in the lines of:

$.ajax({
  dataType: 'json',
  url:  "getmessages.php?lastindex="+this.lastindex,
  type: 'GET',
  async: false,
  success: function(data){
      gup.lastindex=data.lastindex;
      $.each(data.updates, function(i,item){
          gup.addUpdate(item);
      });
});