Spring容器本身没有提供Bean的线程安全策略,因此,也可以说Spring容器中的bean不是线程安全的

​ 如何处理线程安全问题,分情况讨论:

​ Spring的作用域(scope):

  • singleton:单例,默认作用域。

  • prototype:原型,每次创建一个新对象。

  • request:请求,每次Http请求创建一个新对象,适用于WebApplicationContext环境下。

  • session:会话,同一个会话共享一个实例,不同会话使用不用的实例。

  • global-session:全局会话,所有会话共享一个实例。

线程安全问题:

1>对于prototype作用域,每次都生成一个新的对象,所以不存在线程安全问题。

2>对于singleton作用域,默认就是线程不安全的。但是对于开发中大部分的bean,其实都是无状态的,不需要保证线程安全。

无状态:表示这个实例没有属性对象,不能保存实数据,是不变的类。比如:controller、service、dao。

有状态:表示实例是有属性的对象,可以保存数据,是线程不安全的,比如:pojo。

但是如果要保证线程安全,可以将bean的作用域改为prototype,比如像Model View。

另外还可以采用ThreadLocal来解决线程安全问题。ThreadLocal为每个线程保存一个副本变量,每个线程只操作自己的副本变量。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐