spring单例在高并发下可能出现的错误

标签: spring 错误 | 发表时间:2017-01-10 10:32 | 作者:windpoplar
分享到:
出处:http://www.iteye.com

spring单例在高并发下可能出现的错误

 

spring单例在高并发下可能出现的错误: 首先,只有当注入的对象是无状态的幂等的才可以保证执行前后不被修改,否则执行一次之后单例对象就会发生改变,在下次执行有肯能造成结果不一样,当在高并发的情况下就会出现,这个线程刚使用单例对象进行属性设置,还未使用的情况下,另一个进程已经将单利对象的数据进行修改属性完成,则远来线程获取到的单例就是一个脏对象不可使用。 当单例对象中含有变化的变量数据,则就不可以使用对象注入的形式注入,那怎么办? 1、在单例对象中进行new对象,这属于线程自己的内存进行存放数据,其他线程无法使用 2、在单例对象中注入了可变对象,则在使用的时候进行copy浅拷贝后使用拷贝后的对象不实用单例对象 3、通过new Callable()轻量级的创建局部变量可以使用上下文变量,属于线程自己的变量 总结:在高并发情况下,单利对象的数据不可以在一个线程使用过,另一个线程调用时单例对象的数据发生改变。 其实单例对象相当于全局变量,线程执行时需要修改数据,再高并发的情况下就会出现当前线程获取到的单例对象数据是脏数据。

 

Spring单例与线程安全小结

一、Spring单例模式与线程安全

 

 
Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。

 

单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单列状态的修改(体现为该单列的成员属性),则必须考虑线程同步问题
同步机制的比较  ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。 
 
  在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。 
 
  而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。 
 
  由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用
 概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。 
 
  Spring使用ThreadLocal解决线程安全问题 
 
  我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。 
 
  一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。 
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。   线程安全问题都是由全局变量及静态变量引起的。  
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
1) 常量始终是线程安全的,因为只存在读操作。 
2)每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
3)局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象  ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象  .不能保存数据,是不变类,是线程安全的。
有状态对象:
无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。
Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [spring 错误] 推荐:

Spring MVC的常见错误

- - Java译站
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准. 然而多年过后,我发现Spring MVC已经越来越流行了. 对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性. 从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误.

Spring验证的错误返回------BindingResult

- - Java - 编程语言 - ITeye博客
最近做的一个项目使用了 Spring MVC3, 其中验证也是使用Spring的 validate 框架, 但不是全部. 我们 只是使用了org.springframework.validation.Errors, org.springframework.validation.BindingResult 来将验证错误信息返回到JSP页面.

spring单例在高并发下可能出现的错误

- - 互联网 - ITeye博客
spring单例在高并发下可能出现的错误. spring单例在高并发下可能出现的错误: 首先,只有当注入的对象是无状态的幂等的才可以保证执行前后不被修改,否则执行一次之后单例对象就会发生改变,在下次执行有肯能造成结果不一样,当在高并发的情况下就会出现,这个线程刚使用单例对象进行属性设置,还未使用的情况下,另一个进程已经将单利对象的数据进行修改属性完成,则远来线程获取到的单例就是一个脏对象不可使用.

Spring MVC 和 Struts2

- - CSDN博客架构设计推荐文章
Web层面的框架学习了三个Struts1和2,SpringMVC,那他们之间肯定存在一个优劣和适用的环境,Struts1和2的异同点我已经做过对比《 Struts1和Struts2》,这篇将对比下Struts2和SpringMVC的异同,下面数据基本来源于网络,本人是搜集整理所得,供大家参考. 一个项目使用什么样的技术,决定的因素很多,我所能想到的有:对系统的性能、开发的效率、团队学习的成本、业务场景等,下面尽量从这几个方面入手,来分析比较下他们之间存在的优劣.

Spring详解

- - CSDN博客架构设计推荐文章
Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目的是简化企业开发.. PersonDaoBean 是在应用内部创建及维护的. 所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的.

Spring定时

- - 行业应用 - ITeye博客
spring的定时任务配置分为三个步骤:. <!--要定时执行的方法-->. <!--指定要定时执行的方法所在类,将定时任务定义成bean-->. <!--指定定时执行的方法-->. <!--指定目标封装为有状态的任务,有状态的任务不能并发执行,无状态的任务可并发执行-->.

简单Spring+hessian

- - Web前端 - ITeye博客
简单的Spring+hessian. dist\modules里面的 spring-webmvc.jar . lib\caucho 里面的hessian-3.1.3.jar. 里面有个接口interface:. 建立一个model层:(实现Serializable接口). 在WEB-INF下面创建一个remoting-servlet.xml:.

spring roo 入门

- - 企业架构 - ITeye博客
Spring官网下载STS(如果没有STS). 创建Spring Roo基础项目. 根 据ROO的提示输入jpa setup再按ctrl+space,很遗憾这个快捷键已经被输入法切换占用,不能借助提示输入命令,但我们可以打开ROO命令向导,这里我们输入jpa 可以查到这条命令的用法,根据提示增加provider和database选项来完成命令.

Spring Rmi配置

- - 企业架构 - ITeye博客
现在远程调用一般用RPC,webservice或者Rmi,而目前用的比较多的是webservice和Rmi. webservice和rmi的最主要的区别,rmi的客户端和服务端都必须是java,webservice没有这个限制,webservice是在http协议上传递xml文本文件. 与语言和平台无关,rmi是在tcp协议上传递可序列化的java对象,只能用在java虚拟机上,绑定语言.

Spring AOP详解

- - Java - 编程语言 - ITeye博客
        最近项目中遇到了以下几点需求,仔细思考之后,觉得采用AOP来解决. 一方面是为了以更加灵活的方式来解决问题,另一方面是借此机会深入学习Spring AOP相关的内容. 例如,以下需求不用AOP肯定也能解决,至于是否牵强附会,仁者见仁智者见智. 1.对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况.