> 馆藏中心

异步调用等待期间数据被篡改导致数据不一致问题!

来源:cnblogs 编辑:王强

jquery ajax是个很常用接口,而在请求时2113候,可能存在响应401的情5261况(身份4102认证过期或未登录),比较容易1653出现在混合应用上,如何进行身份认证,重发失败请求,还是值得注意的。ajax请求有两种方式1. 回调最常写的方式,成功失败处理以回调方式传入。$.ajax({ ajax参数... success : xxxxxx error: xxxxxx }); 2. Deferred方式Deferred模式我在《js异步编程》有说明, ajax调用本身返回就是一个Deferred对象,成功失败回调不以参数传入。$.ajax({ ajax参数... }).then(function(res){ //成功处理片段 },function(err){ //失败处理片段 }); 既然有这两种方式,那应对处理401的方式也是有两种。401处理的两种方式1. 回调这种方式的处理比较简单,在失败回调里面判断401,如果是则进行身份认证,成功重发请求。function getXXXX(type, url, data, success, error){   $.ajax({   ajax参数...    success : xxxxxx    error : function(xhr,textStatus,errorThrown){   if (xhr.status == 401) {      刷新身份认证方法(function(){   getXXXX(type, url, data, success, error);   });  } else{   // 调用外部的error   error && error(xhr,textStatus,errorThrown);    }   }   }); } 2. Deferred方式这种方式目前我找到的处理方式需要修改jquery源码。//全局设置一个方法 $.ajaxSetup({ authError : function(callback){ 刷新身份认证方法( function(){ callback && callback(); }); } }); //jquery2.1.4版本源码,大概是8261行 // Success/Error if ( isSuccess ) { deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); } else { if(( jqXHR.status == 401 || jqXHR .status == 403) && callbackContext.authError){   callbackContext.authError(function (){ state = 0; jqXHR.setRequestHeader( "Authorization", XXXXXX); jqXHR.readyState = 1; try { state = 1; transport.send( requestHeaders, done ); } catch ( e ) { // Propagate exception as error if not done if ( state < 2 ) { done( -1, e ); // Simply rethrow otherwise } else { throw e; } }   });   return; } else { deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); } } 这里说下为什么不能像第一种方式那样进行请求。有两个原因:1. then这种链式写法,导致这请求的回调不是在参数里,而是在jQuery.Callbacks一个optionsCache全局变量里,我们无法在ajax error里拿到回调函数进行重发。2. 写在then里的回调触发一次就会被销毁,当触发了error时,回调执行后就销毁。最后的处理方式就是在要触发error之前,拦截401的错误,重新进行身份认证,然后重置状态,重发请求。以上这篇当jquery ajax遇上401请求的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家www.179s.com防采集请勿采集本网。

很简单实现啊,同步操作换个逻辑把要改的内容放在异步的使用的队列中就好了,如果你异步加锁就毫无意义做异步,干脆同步和异步共用一个队列收获园豆:50没太看清楚你的逻辑。消息队列就是 把 任务(或者数据)串行化,既然是串行化,哪里还有所谓并发,就是挨个挨个执行,也就不存在所谓的絮乱。所有的操作都做成异步的,不存在同步操作了

总的结论:java是线程安全的,即2113对5261任何方法(包括静态方法)都可以不考虑线程冲突4102,但有一1653个前提,就是不能存在全局变量。如果存在全局变量,则需要使用同步机制。如下通过一组对比例子从头讲解: 在多线程中使用静态方法会发生什么事?也就是说多线程访问同一个类的static静态方法会发生什么事?是否会发生线程安全问题?public class Test { public static void operation(){ // ... do something }} 事实证明只要在静态函数中没有处理多线程共享数据,就不存在着多线程访问同一个静态方法会出现资源冲突的问题。下面看一个例子:public class StaticThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub StaticAction.print(); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new StaticThread()).start(); } }}public class StaticAction { public static int i = 0; public static void print() { int sum = 0; for (int i = 0; i < 10; i++) { System.out.print("step " + i + " is running."); sum += i; } if (sum != 45) { System.out.println("Thread error!"); System.exit(0); } System.out.println("sum is " + sum); }} 实际执行的结果显示各个线程对静态方法的访问是交叉执行的,但是这并不影响各个线程静态方法print()中sum值的计算。也就是说,在此过程中没有使用全局变量的静态方法在多线程中是安全的,静态方法是否引起线程安全问题主要看该静态方法是否对全局变量(静态变量static member)进行修改操作。 在多线程中使用同一个静态方法时,每个线程使用各自的实例字段(instance field)的副本,而共享一个静态字段(static field)。所以说,如果该静态方法不去操作一个静态成员,只在方法内部使用实例字段(instance field),不会引起安全性问题。 但是,如果该静态方法操作了一个静态变量,则需要静态方法中采用互斥访问的方式进行安全处理。我们来看一下没有使用互斥访问的话会产生怎样的问题:public class StaticAction { public static int i = 0; public static void incValue() { int temp = StaticAction.i; try { Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } temp++; StaticAction.i = temp; }}public class StaticThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub StaticAction.incValue(); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new StaticThread()).start(); } try { Thread.sleep(1000); //预留足够的时间让上面的线程跑完 } catch (Exception e) { e.printStackTrace(); } System.out.println(StaticAction.i); }} 实际运行结果显示i值为随机的数字。为了实现互斥访问,这时我们需要加入一个synchronized关键字。代码修改如下:public class StaticAction { public static int i = 0; public synchronized static void incValue() { int temp = StaticAction.i; try { Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } temp++; StaticAction.i = temp; }}public class StaticThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub StaticAction.incValue(); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new StaticThread()).start(); } try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } System.out.println(StaticAction.i); }} 运行结果则必然是100。 加入synchronized关键字的静态方法称为同步静态方法。 在访问同步静态方法时,会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。这个其实就是操作系统中的用信号量实现进程的互斥与同步问题,如果涉及在同一个类中有多个静态方法中处理多线程共享数据的话,那就变成用信号量解决生产者-消费者问题。也就是说,静态方法是一份临界资源,对静态方法的访问属于进入临界区;对静态变量的修改是一份临界资源,对静态变量的修改属于进入临界区,并发能产生问题的情况是,两个线程都去竞争同一个对象才会产生问题,如果你的静态方法只是简单的逻辑是不会有问题的,但是如果你的线程都是去修改静态变量的值的话,应该是会造成线程问题的本回答被网友采纳,多线程通常主要怕资源争抢问题发生,如果你调用的类只是一个访问不修改值,不存在问题。如果修改就会带来资源混乱,这时就得作出相应的处理,加锁同步,也许会有问题,要看你的方法里面写了什么逻辑咯,一般静态方法里如果没有共享资源(全局变量或缓存等)或者锁(不会产生资源竞争)的话,是没问题的内容来自www.179s.com请勿采集。

本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。本文《异步调用等待期间数据被篡改导致数据不一致问题!》转载自cnblogs,版权归原作者所有,若侵权请联系:E-MAIL:513175919@qq.com
违法违规信息请立即联系本网可获得现金奖励,TEL:1-8-2-1-0-2-3-3-3-8-1(电话仅供违法违规信息举报,侵权类信息请EMAIL。)

www.179s.com false 互联网 http://www.179s.com/jsblogcnk/po/pokpvj.html report 6077 很简单实现啊,同步操作换个逻辑把要改的内容放在异步的使用的队列中就好了,如果你异步加锁就毫无意义做异步,干脆同步和异步共用一个队列收获园豆:50没太看清楚你的逻辑。消息队列就是 把 任务(或者数据)串行化,既然是串行化,哪里还有所谓并发,就是挨个挨个执行,也就不存在所谓的絮乱。所有的操作都做成异步的,不存在同步操作了

热门图片

经济金融企业管理法律法规社会民生科学教育降生活体育运动文化艺术电子数码电脑网络娱乐休闲行政地区心理分析医疗卫生