Spring单例模式下的多线程访问
一直以来有个疑问?
Spring中的bean不是单例模式吗?为什么那么多客户端访问同一个接口不会出现线程安全问题?
其实:
- spring单例模式指的是在内存中只实例化一个类的对象。确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
- 当多个用户同时请求一个接口服务的时候,容器会给每一个请求分配一个线程,这时候多个线程会并发执行该请求所对应的业务逻辑。如果该逻辑涉及到对该单例状态(成员变量)的改变,就会有线程安全的问题。
- Spring使用ThreadLocal来解决线程安全问题,每个线程去执行业务代码的时候,都会去内存申请临时变量,这样就不会涉及变量并发访问冲突的问题。
- 一般的 Web 应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。
那JVM是如何实现线程的独立内存空间?
- 每当启用一个线程时,JVM就为他分配一个Java栈,栈是以帧为单位保存当前线程的运行状态。某个线程正在执行的方法称为当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。当线程执行一个方法时,它会跟踪当前常量池。
- 每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前帧。当执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等。
- Java栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据。所以我们不用考虑多线程情况下栈数据访问同步的情况。