• 单例模式中可能存在的一些问题(线程安全问题)


    单例的设计模式中,一些代码的写法会存在线程安全的问题,举例如下:

    (1)单例模式的懒汉式[线程不安全,不可用]

        public class Singleton {  
          
            private static Singleton instance=null;  
              
            private Singleton() {};  
              
            public static Singleton getInstance(){  
                  
                if(instance==null){  
                    instance=new Singleton();  
                }  
                return instance;  
            }  
        }  

    这种方式是在调用getInstance方法的时候才创建对象的,所以它就被称为懒汉模式。

    这是存在线程安全问题的,那具体是存在怎样的线程安全问题?怎样导致这种问题的?好,我们来说一下什么情况下这种写法会有问题。在运行过程中可能存在这么一种情况:多个线程去调用getInstance方法来获取Singleton的实例,那么就有可能发生这样一种情况,当第一个线程在执行if(instance==null)时,此时instance是为null的进入语句。在还没有执行instance=new Singleton()时(此时instance是为null的)第二个线程也进入了if(instance==null)这个语句,因为之前进入这个语句的线程中还没有执行instance=new Singleton(),所以它会执行instance = new Singleton()来实例化Singleton对象,因为第二个线程也进入了if语句所以它会实例化Singleton对象。这样就导致了实例化了两个Singleton对象。所以单例模式的懒汉式是存在线程安全的,既然它存在问题,那么可能有解决办法,于是就有下面加锁这种写法。

    (2)懒汉式线程安全的[线程安全,效率低不推荐使用]

    public class Singleton {  
      
        private static Singleton instance=null;  
          
        private Singleton() {};  
          
        public static synchronized Singleton getInstance(){  
              
            if(instance==null){  
                instance=new Singleton();  
            }  
            return instance;  
        }  
    } 

    缺点:效率太低了,每个线程在想获得类的实例的时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面想获得该实例,直接return就行了。方法进行同步效率太低要改进。

    (3)单例模式懒汉式[线程不安全,不可用]

    public class Singleton7 {  
      
        private static Singleton instance=null;  
          
        public static Singleton getInstance() {  
            if (instance == null) {  
                synchronized (Singleton.class) {  
                    instance = new Singleton();  
                }  
            }  
            return instance;  
        }  
    }

    这种写法也是不安全的,当一个线程还没有实例化Singleton时另一个线程执行到if(instance == null)这个判断时语句机会进入if语句,虽然加了锁,但是等到第一个线程执行完instance=new Singleton()跳出这个锁时,另一个进入if语句的线程同样会实例化另外一个SIngleton对象。因为这种改进方法不可行。

    (4)单例模式懒汉式[线程安全,可用]

    public class Singleton7 {  
      
        private static Singleton instance=null;  
          
        public static Singleton getInstance() {  
            if (instance == null) {  
                synchronized (Singleton.class) {  
                    if (instance == null) {  
                        instance = new Singleton();  
                    }
                }  
            }  
            return instance;  
        }  
    }

    (5)单例模式饿汉式[线程安全,可用]

    public class Singleton1 {  
        private Singleton1() {}  
        private static final Singleton1 single = new Singleton1();  
        //静态工厂方法   
        public static Singleton1 getInstance() {  
            return single;  
        }  
    } 

     

    饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

    (6)单例模式的成员变量[线程不安全,不可用]

    public class Singleton {  
        int i =0;
        private Singleton() {}  
        private static final Singleton1 single = new Singleton1();  
        //静态工厂方法   
        public static Singleton1 getInstance() {  
            i++;        
            return single;  
        }  
    }     

    这种写法也是不安全的,当一个线程还没有执行到i++时另一个线程执行到int i=0,导致i=1而不是2,应改为局部变量写法较好

    总结:

    以上就是单例模式中,会引发的线程安全问题了

  • 相关阅读:
    关于XCode5打开工程闪退的一种解决方案
    【转】iOS应用崩溃日志揭秘
    Cocos2d-X中字符串的处理
    【转】不要把大脑当做磁盘
    【ybt金牌导航6-3-2】区间计数(分块)(二分)
    【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)
    【ybt金牌导航6-2-2】【luogu CF600E】树上众数 / Lomsat gelral(树上启发式合并)
    【ybt金牌导航6-1-5】最大割(线段树分治)(线性基)
    【luogu CF1100F】Ivan and Burgers
    【ybt金牌导航8-1-4】【luogu P4151】路径最大异或和 / 最大XOR和路径
  • 原文地址:https://www.cnblogs.com/ithfm/p/10280910.html
Copyright © 2020-2023  润新知