Spring问题 之创建好的单例对象是否存在线程安全问题

Spring的Bean作用域

作用域字符描述
单例singleton整个应用中只创建一个实例
原型prototype每次注入时都新建一个实例
会话session为每个会话创建一个实例
请求request为每个请求创建一个实例

默认的是:单例 singleton

创建单例的方式是否线程安全

懒汉式(不安全写法):

public class Singleton{ 
    private Singleton(){}
    private static Singleton singleton = null;  //不建立对象
    public static Singleton getInstance(){
		if(singleton == null) {        //先判断是否为空
			singleton = new Singleton ();  //懒汉式做法 
		}
		return singleton;
     }
}

饿汉式(不存在线程安全问题):

public class Singleton{ 
    public Singleton(){}
    private static Singleton singleton = new Singleton()//建立对象
    public static Singleton getInstance(){
  		return singleton;//直接返回单例对象 }
}

懒汉式(安全写法):

public class Singleton{ 
    private Singleton(){}
    private static Singleton singleton = null;  //不建立对象
    public static synchronized Singleton getInstance(){
             if(singleton == null) {        //先判断是否为空
                 singleton = new Singleton ();  //懒汉式做法 
             }
             return singleton ;
     }
}

怎么判断使用已经创建好的单例对象是否线程安全

  • 看这个单例里有没有全局变量(全局变量就是成员变量,成员变量又分实例变量和静态变量)
  • 如果有全局变量,看它是不是只可以读取而不能写入(有没有发布set方法)

如果满足上面两个条件,那么这个单例就是不安全的。

Spring的单例模式与线程安全

Spring框架里的bean获取实例的时候都是默认单例模式,所以在多线程开发里就有可能会出现线程不安全的问题。当多个用户同时请求一个服务器时,容器(tomcat)会给每一个请求分配一个线程,这时多个线程会并发执行该请求所对应的业务逻辑(controller里的方法),此时就要注意啦,如果controller(是单例对象)里有全局变量并且又是可以修改的,那么就需要考虑线程安全的问题。
解决方案有很多,比如设置@scope(“prototype”)为多例模式,为每个线程创建一个controller,还可以使用ThreadLocal。

ThreadLocal基本实现思路是:它会为每个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突,因为每个线程都拥有自己的变量副本,从而也就没必要对该变量进行同步啦。

在ssh或ssm框架里的service或dao对象虽然也是单例模式,但正如上面分析的,他们没有可修改的全局变量,所以在多线程环境下也是安全的。

有状态对象和无状态对象

无状态对象:无法存储数据,不存在线程安全问题。
有状态对象:有数据存储功能,多线程环境下存在线程安全问题。

其实如果一个有状态对象且没有set方法只是可读,其实也是安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值