spring单例,controller、service和dao能保证线程安全?

1,572 阅读2分钟

  Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。
  实际上大部分时间Bean是无状态的(比如Dao) 所以说在某种程度上来说Bean其实是安全的。  但是如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。

  有状态就是有数据存储功能,无状态就是不会保存数据,例如在Service中定义成员变量,那么这就是不安全的。

  controller、service和dao层本身并不是线程安全的,只是如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。所以只要你不在userConstroller里修改userService这个实例就没问题。所以调用方法时,会把局部变量封闭到线程类,调用方法不涉及到全局变量,完全不用担心线程安全问题。一般来说,也不会修改service。
  想理解原理可以看看《深入理解JVM虚拟机》,2.2.2节:

Java虚拟机栈是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

  《Java并发编程实战》第3.2.2节:

局部变量的固有属性之一就是封闭在执行线程中。 它们位于执行线程的栈中,其他线程无法访问这个栈。   所以其实任何无状态单例都是线程安全的。

还有一点,如果再servcie里修改service的全局变量,也不是线程安全的。就是一点,方法中的局部变量线程安全,方法外的成员变量或者全部变量,或者所谓的全局缓存之类的,不是线程安全。