为AJAX实现互斥

随着AJAX范例得到越来越广泛的应用,浏览器页面可以在向后台服务器请求数据的同时保持前端用户界面的活跃性(因此在AJAX中称为异步)。然而,当这两个活动同时访问共用的JavaScript和DOM数据结构时就会引发问题。JavaScript没有提供针对该并发程序问题的经典解决方案。本文描述了作者在互斥机制方面的新见解,该经过验证的互斥机制在JavaScript中能发挥良好的作用。

为什么需要互斥?

当多个程序逻辑线程同时访问相同数据的时候,问题便产生了。程序通常假定与其交互的数据在交互过程中不发生改变。访问这些共享数据结构的代码称为临界区,一次只允许一个程序访问的机制被称为互斥。在AJAX应用程序中,当对来自XMLHttpRequest的应答进行异步处理的代码同时操纵正在被用户界面使用的数据时,便会发生这种情况。这个共用的数据可能是用于实现MVC数据模型的JavaScript和/或web页面自身的DOM。如果二者中的任一个对共享数据做了不协调的更改,那么二者的逻辑都将中断。

也许您会说“等等,为什么我没有遇到过这种问题?”。遗憾的是,这种问题是同步依赖的(也叫做竞态条件),因此它们并不总是发生,或者也许从不发生。它们的或然性基于许多因素。基于健壮性考虑,富internet应用程序应该通过确保这些问题不会发生来阻止出现这种情况。

因此,需要一种互斥机制来确保同时只能打开一个临界区,并且在它结束之后才能打开另一个。在大多数主流计算机语言和执行框架中,都提供互斥机制(经常是几种),但是应用于浏览器端的JavaScript却没有提供这种互斥机制。虽然存在一些无需专门的语言或环境支持的经典互斥实现算法,但是即使这样还是需要一些JavaScript和浏览器(如Internet Explorer)所缺少的要素。接下来介绍的经典算法在这些浏览器和语言中能发挥良好的作用。

面包店算法

在计算机科学文献中的几种互斥算法中,所谓的Lamport面包店算法可以有效地用于多个相互竞争的控制线程,该算法中线程之间的通信只能在共享内存中进行(即,不需要诸如信号量、原子性的set-and-test之类的专门机制)。该算法的基本思想源于面包店,因为面包店需要先取号然后等候叫号。清单1给出了该算法的框架(引自Wikipedia),该算法可以使各线程进出临界区而不产生冲突。

清单1. Lamport面包店算法伪代码

// declaration & initial values of global variables
Enter, Number: array [1..N] of integer = {0};
// logic used by each thread...
// where "(a, b) < (c, d)"
// means "(a < c) or ((a == c) and (b < d))"
Thread(i) {
 while (true) {
  Enter [i] = 1;
  Number[i] = 1 + max(Number[1],...,Number[N]);
  Enter [i] = 0;
  for (j=1; j<=N; ++j) {
   while (Enter[j] != 0) {
    // wait until thread j receives its number
   }
   while ((Number[j]!=0)
     && ((Number[j],j) < (Number[i],i))) {
    // wait until threads with smaller numbers
    // or with the same number, but with higher
    // priority, finish their work
   }
  }
  // critical section...
  Number[i] = 0;
  // non-critical section...
 }
}

如上所示,该算法假定各线程清楚自己的线程编号(常量i)和当前正在活动的线程总数(常量N)。此外,还假定存在一种等待或休眠方式,例如:暂时将CPU释放给其他线程。遗憾的是,Internet Explorer中的JavaScript没有这种能力。虽然如此,如果实际运行在同一线程上的多个代码部分表现为各自运行在独立的虚拟线程上,那么该面包店算法不会中断。同样,JavaScript具有一种在指定延迟后调度函数的机制,所以,可以使用下面的这些方法来优化面包店算法。

Wallace变体

在JavaScript中实现Lamport面包店算法的主要障碍在于缺少线程API。无法确定当前正在哪个线程上运行以及当前正在活动的线程数目,也无法将CPU释放给其他的线程,无法创建新的线程来管理其他线程。因此,无法查证如何将特定的浏览器事件(例如:单击按纽、可用的XML应答等)分配到线程。

克服这些障碍的一种方法是使用Command设计模式。通过将所有应该进入临界区的逻辑以及所有启动该逻辑所需的数据一起放入到command 对象中,可以在负责管理command的类中重写面包店算法。该互斥类仅在没有其他临界区(封装为独立的command对象方法)在执行时调用临界区,就像它们各自运行在不同的虚拟线程中一样。JavaScript的setTimeout()机制用于将CPU释放给其他正在等待的command。

为command对象假定一个简单的基类(见清单2中的Command),可以定义一个类(见清单3中的Mutex)来实现面包店算法的Wallace变体。注意,虽然可以通过很多方式在JavaScript中实现基类对象(为了简洁起见,这里使用一种简单的方式),但是只要各个command对象拥有某个惟一的id,而且整个临界区被封装在单独的方法中,那么任何对象模式都可以使用这种方法。

时间: 2024-07-28 19:03:37

为AJAX实现互斥的相关文章

在AJAX程序中实现互斥揭秘

ajax|程序 随着AJAX范例得到越来越广泛的应用,浏览器页面可以在向后台服务器请求数据的同时保持前端用户界面的活跃性(因此在AJAX中称为异步).然而,当这两个活动同时访问共用的JavaScript和DOM数据结构时就会引发问题.JavaScript没有提供针对该并发程序问题的经典解决方案.本文描述了作者在互斥机制方面的新见解,该经过验证的互斥机制在JavaScript中能发挥良好的作用. 为什么需要互斥? 当多个程序逻辑线程同时访问相同数据的时候,问题便产生了.程序通常假定与其交互的数据在

从零开始学_JavaScript_系列(七)——jquery(复选框及互斥、div块、修改css、标签数组、ajax连续加载)

(17)查看复选框是否被选中 复选框为: <input type="checkbox" name="yingmingliu"id="yingmingliu" value="yingmingliu"/> jq语法为: $("#yingmingliu").is(':checked') 如果选中,返回true,如果没有被选中,返回false.   查看复选框的值: $("#yingmingl

jQuery同步Ajax带来的UI线程阻塞问题及解决办法

遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责获取数据,然后把数据return.基本的逻辑剥离出来是这样的: function getData1(){         var result;         $.ajax({             url : "p.php",             async : false,  

简单的JavaScript互斥锁分享

 这篇文章主要介绍了简单的JavaScript互斥锁的相关资料,需要的朋友可以参考下 去年有几个项目需要使用JavaScript互斥锁,所以写了几个类似的,这是其中一个:     复制代码 代码如下: //Published by Indream Luo //Contact: indreamluo@qq.com //Version: Chinese 1.0.0   !function ($) {     window.indream = window.indream || {};     $.i

Jquery ajax 同步阻塞引起的UI线程阻塞问题_jquery

最近做一个项目,遇到了一个问题同步ajax引起的ui线程阻塞问题,下面把我的问题解决过程分享给大家. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责获取数据,然后把数据return.基本的逻辑剥离出来是这样的: function getData1(){ var result; $.ajax({ url : "p.php", async : false, success: function(d

jQuery Ajax同步参数导致浏览器假死怎么办

事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责获取数据,然后把数据return.基本的逻辑剥离出来是这样的:    代码如下 复制代码 function getData1(){        var result;         $.ajax({             url : 'p.php',             async : false,             success: fu

Ajax 提交表单数据到入库的全盘操作流程

 以下是Ajax 提交表单数据到入库的全盘操作流程,希望本文对广大php开发者有所帮助,感谢阅读本文 *******php项目中当我们要对数据库进行写入操作时,有时会因为代码没有做防sql注入工作,导致各种不可预知的错误*******    1,index.htm 这是一个很简单的注册页面l 我这是以ajax形式提交数据   代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt

ajax浏览器兼容的问题探讨

 ajax浏览器兼容的问题一直都是同学们多烦恼的,下面有个不错的示例大家可以参考下,希望对大家有所帮助  代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xht

ajax同步异步的简单实现

本文为大家介绍下ajax同步异步的简单实现,感兴趣的朋友可以参考下 复制代码 代码如下: $("#btn_saveFWSB").click(function(){  var obj=checkData(arr);  if(obj.flag==true){  hideAddDiv();  $.ajax({  type : "POST",  url : "/vts/doInsertFWZT.do",  async: false ,//ajax同步