设计模式。双重检查单例(优化到极致完美),解决单例懒汉式的线程不安全

Posted 安果移不动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式。双重检查单例(优化到极致完美),解决单例懒汉式的线程不安全相关的知识,希望对你有一定的参考价值。

上文讲到

单纯的加锁就可以

package com.yzdzy.design.singleton;

/**
 * 加锁

 */
public class Mgr04 
    private static Mgr04 mInstance;


    private Mgr04() 
    

    public static synchronized Mgr04 getInstance() 

        if (mInstance == null) 
            // 两个线程里面 会创建多个实例。
            try 
                Thread.sleep(1);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            mInstance = new Mgr04();
        
        return mInstance;
    
    public void m() 
        System.out.println("m");
    
    public static void main(String[] args) 

        for (int i = 0; i < 10; i++) 
            new Thread(() -> 
                System.out.println(Mgr04.getInstance().hashCode());
            ).start();
        
    


but 效率低了对吗

那么有人尝试通过锁同步代码的方式去解决

package com.yzdzy.design.singleton;


public class Mgr05 
    private static Mgr05 mInstance;


    private Mgr05() 
    

    public static Mgr05 getInstance() 

        if (mInstance == null) 
            // 妄图通过减小同步代码库的方式提高效率,然后不可行
            synchronized (Mgr05.class) 
                try 
                    Thread.sleep(1);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
                mInstance = new Mgr05();
            
        

        return mInstance;

    

    public void m() 
        System.out.println("m");
    

    public static void main(String[] args) 

        for (int i = 0; i < 10; i++) 
            new Thread(() -> 
                System.out.println(Mgr05.getInstance().hashCode());
            ).start();
        
    


解决了吗

没有。

> Task :Mgr05.main()
1288032892
1696172314
1098833185
471895473
334817404
541982512
662136803
1722732360
1133601195
1313614725

因为他还是持有了懒加载的间隔  和最初的懒加载拥有相同的诟病

解决方案应势而生

双重检查

package com.yzdzy.design.singleton;

/**
 * 懒汉式
 * lazy loading
 * 优点:按需初始化,什么时候用什么时候才初始化
 * 缺点:线程不安全
 */
public class Mgr06 
    //jit volatile 解决指令重排
    private static volatile Mgr06 mInstance;


    private Mgr06() 
    

    public static Mgr06 getInstance() 

        if (mInstance == null) 
            // 妄图通过减小同步代码库的方式提高效率,然后不可行
            synchronized (Mgr06.class) 
                if (mInstance == null) 
                    try 
                        Thread.sleep(1);
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                    mInstance = new Mgr06();
                
            
        

        return mInstance;

    

    public void m() 
        System.out.println("m");
    

    public static void main(String[] args) 

        for (int i = 0; i < 10; i++) 
            new Thread(() -> 
                System.out.println(Mgr06.getInstance().hashCode());
            ).start();
        
    


> Task :Mgr06.main()
1288032892
1288032892
1288032892
1288032892
1288032892
1288032892
1288032892
1288032892
1288032892
1288032892

以上是关于设计模式。双重检查单例(优化到极致完美),解决单例懒汉式的线程不安全的主要内容,如果未能解决你的问题,请参考以下文章

最完美的单例模式

最完美的单例模式

最完美的单例模式

最完美的单例模式

单例模式双重检查(DCL)引发的多线程问题

如何实现一个单例模式 c#双重锁检查