1、spring框架controller和service默认都是单例的,那么多并发时,是如何实现线程安全的?
A、每当启用一个线程时,JVM就为他分配一个Java栈,栈是以帧为单位保存当前线程的运行状态。某个线程正在执行的方法称为当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量称为当前常量池。当线程执行一个方法时,它会跟踪当前常量池。
B、每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前帧。当执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等。
C、Java栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据。所以我们不用考虑多线程情况下栈数据访问同步的情况。
D、如上,则@Controller是单例模式,即一个对象只有一个实例。通过线程副本[栈]的模式实现并发访问
2、线程副本与安全问题 线程副本通过栈和帧实现线程隔离,达到并发访问的目的,那么有没有前提呢?
A、如上所述,局部变量和中间运算结果集参数是线程隔离==>安全的,但是成员变量则是会受到多线程调用影响的
B、那Controller里面的service都是成员变量,会受影响么?service也是单例,其主要用来实现方法调用,就会进入帧的切换从而转变为中间结果的问题,同理单例的service的成员变量和局部变量的线程隔离性同Controller。
PS:Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态。
TransactionSynchronizationManager对资源resources采用ThreadLocal保管,就是dao的SqlSession[亦即getConnection]的由来
C、对应的成员变量就被暴露在所有线程面前了,所以最好用ThreadLocal保护起来,实现线程安全。