1 Spring框架中的bean是单例的吗?
默认是单例的,一般情况下,单例模式不会有线程安全问题。
singleton模式(默认模式)
如果该bean的类定义,注解是@Scopre("singleton"),则说明该类的bean实例在spring容器中,有且仅有一个实例对象,此时可以说bean是单例的;同时,这也是spring中默认的模式。
prototype
如果注解是@Scopre("prototype"),则每一次调用该bean时,都会在容器中新建一个bean对象。“这种情况下,每个bean基本都是线程安全的”
@Service
@Scope("singleton")
public class UserServiceImpl implements UserService {
}
- singleton : bean在每个Spring IOC容器中只有一个实例。
- prototype:一个bean的定义可以有多个实例。
2 Spring框架中的单例bean是线程安全的吗?
- 大多数情况下,可以说是线程安全的。
- Spring的bean大部分时候是线程安全的,其所注入的一般都是无状态对象(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。
- 但是,如果该bean定义了可修改的成员变量,就会存在线程不安全的情况;需要考虑改成多例或者加锁来解决。
代码示意
依赖注入的Service和Dao (安全的)
在该bean中,依赖注入的UserService类的bean是一个无状态的实例对象,该bean不能被修改,是线程安全的。
方法形参(安全的)
该bean的getByid方法,其形参(或者方法参数 )Integer id是线程安全的,因为每一次请求方法都会创建一个数据副本,多个线程请求互不影响;
成员参数(不安全的)
该bean的成员变量count,则需要考虑线程安全问题;
因为每个请求过来都会修改这个count,如果并发时,若请求A先读取到0,再进行++,则结果会变成1赋值给count;并发的请求B也是读取到0,但是进行了--操作,则算出结果是-1对count进行赋值; 此刻,count的值可能是1或-1;计算结果都不对;因为正常情况是,对0进行--再++,或是++在--,都应该还是0;
以上知识,先简单理解记忆,基本够用,实际情况更复杂,也不必一步到位,为难自己!!
参考: