参考博客:
https://blog.csdn.net/weixin_43727372/article/details/100324678
https://www.cnblogs.com/xubiao/p/6567349.html
Spring容器本身没有提供Bean的线程安全策略,因此Spring容器中的Bean本身不具备线程安全的特性。
单例和原型是spring bean的两个作用域。
对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然不会有线程安全的问题。
如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。
有状态对象(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。
对于有状态的bean,Spring官方提供的bean,一般提供了通过ThreadLocal去解决线程安全的方法
使用ThreadLocal的好处
使得多线程场景下,多个线程对这个单例Bean的成员变量并不存在资源的竞争,因为ThreadLocal为每个线程保存线程私有的数据。这是一种以空间换时间的方式。
当然也可以通过加锁的方法来解决线程安全,这种以时间换空间的场景在高并发场景下显然是不实际的。
(1、有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
2、无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。)