您的位置:首页 > 编程语言 > Java开发

SpringMvc线程安全问题(个人感悟)

2018-03-30 09:18 246 查看
由于springmvc是singleton的,所以假如存在全局变量时就容易导致线程安全问题,线程安全问题其实归根结底就是数据共享问题,这就又牵扯到java虚拟机的内存结构了,每一个线程都会有自己的工作内存,还有一块公用的内存,共享内存,我们定义好的一个变量放在共享内存中,每当一个线程对全局变量进行操作时,都会与共享内存中的保存的全局变量的值进行比较。
Spring MVC默认是单例模式,Controller、Service、Dao都是单例所以在使用不当存在一定的安全隐患。Controller单例模式的好处在与: 
1. 提高性能,不用每次创建Controller实例,减少了对象创建和垃圾收集的时间 
2. 没多例的必要 
由于只有一个Controller的实例,当多个线程同时调用它的时候,它的成员变量就不是线程安全的。 
当然在大多数情况下,我们根本不需要Controller考虑线程安全的问题,除非在类中声明了成员变量。因此Spring MVC的Contrller在编码时,尽量避免使用实例变量。如果一定要使用实例变量,则可以改用以下方式: 
1. Controller中声明 scope=”prototype”,即设置为多例模式 
2.在Controller中使用ThreadLocal变量,如:
private ThreadLocal<Integer> count = new ThreadLocal<Integer>();


springmvc singleton有几种解决方法:
1、在控制器中不使用实例变量(可以使用方法参数的形式解决,参考博文 Spring Bean Scope 有状态的Bean 无状态的Bean
2、将控制器的作用域从单例改为原型,即在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
3、在Controller中使用ThreadLocal变量

spring中的并发访问题:我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。
那么对于有状态的bean呢?Spring对一些(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态的bean采用ThreadLocal进行处理,让它们也成为线程安全的状态,因此有状态的Bean就可以在多线程中共享了。

spring对那些个有状态bean使用ThreadLocal维护变量[仅仅是变量,因为线程同步的问题就是成员变量的互斥访问出问题]时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: