zoukankan      html  css  js  c++  java
  • 单例对象线程安全问题

    1.spring的bean作用域

     默认的是:单例 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 ;//直接返回单例对象 }}


    懒汉式在多线程环境下就是线程不安全的,假设有线程1和线程2两个线程,线程1在判断if(singleton == null)的时候,突然失去cpu的执行权,而线程2获得了cpu的执行权,执行了getInstance()方法,创建了个对象,但是这个事情线程1并不知道,线程1重新获得cpu的执行权时,判断if(singleton == null)结果是null,所以又去创建了对象,那么这样就会出现破坏单例的情况,有多余的对象,所以线程是不安全的,解决方案之一就是加锁.

    懒汉式(安全写法)

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

    在spring的框架里,对象是交给spring容器创建的,spring的创建单例的方式既不是懒汉式也不是饿汉式,是单例注册表模式实现单例模式的,这种创建单例模式的方式是线程安全的。

    二、spring的单例模式与线程安全

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

    2.其实spring的源码里比如RequestContextHolderTransactionSynchronizationManagerLoxaleContextHolder等这些对象创建方式也是单例,底层就是用ThreadLocal处理的。ThreadLocal基本实现思路是:它会为每个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突,因为每个线程都拥有自己的变量副本,从而也就没必要对该变量进行同步。

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

  • 相关阅读:
    RocketMQ中Producer消息的发送源码分析
    VS等待调试
    Window&Linux遍历某一文件夹
    遍历当前USB设备信息
    批处理常用符号详解
    Windows 批处理(bat)语法大全
    Windows CMD命令大全(值得收藏)
    遍历文件夹
    ASCII,UTF-8,Unicode字符串相互转换
    shellexecute的使用和X64判断
  • 原文地址:https://www.cnblogs.com/KL2016/p/15131752.html
Copyright © 2011-2022 走看看