设计模式。单例懒汉式(懒得让人觉得不够安全)

Posted 安果移不动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式。单例懒汉式(懒得让人觉得不够安全)相关的知识,希望对你有一定的参考价值。

package com.yzdzy.design.singleton;

/**
 * 懒汉式
 * lazy loading
 * 优点:按需初始化,什么时候用什么时候才初始化
 * 缺点:线程不安全
 */
public class Mgr03 
    private static Mgr03 mInstance;


    private Mgr03() 
    

    public static Mgr03 getInstance() 

        if (mInstance == null) 
            // 两个线程里面 会创建多个实例。
            try 
                Thread.sleep(1);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            mInstance = new Mgr03();
        
        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(Mgr03.getInstance().hashCode());
            ).start();
        
    


线程不安全是为什么

因为如果两个线程可能会出现问题。

不同的对象hashcode是不同的。

通过延时1s可以打印出来

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

非常的不一样。

我们把延迟关闭到就相同的多一点

注释掉的以后

package com.yzdzy.design.singleton;

/**
 * 懒汉式
 * lazy loading
 * 优点:按需初始化,什么时候用什么时候才初始化
 * 缺点:线程不安全
 */
public class Mgr03 
    private static Mgr03 mInstance;


    private Mgr03() 
    

    public static Mgr03 getInstance() 

        if (mInstance == null) 
            // 两个线程里面 会创建多个实例。
//            try 
//                Thread.sleep(1);
//             catch (InterruptedException e) 
//                e.printStackTrace();
//            
            mInstance = new Mgr03();
        
        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(Mgr03.getInstance().hashCode());
            ).start();
        
    


27590626
27590626
27590626
27590626
27590626
27590626
27590626
27590626
27590626
27590626

全部都一样。但是他是因为执行的太快了。所以都相等了。 仍然是存在一点点问题。这一点点问题。还是指的注意的。他并不是线程安全的

如何解决这个问题呢

一个关键字锁 

synchronized
package com.yzdzy.design.singleton;

/**
 * 懒汉式
 * lazy loading
 * 优点:按需初始化,什么时候用什么时候才初始化
 * 缺点:线程不安全
 */
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();
        
    


> Task :Mgr04.main()
1313614725
1313614725
1313614725
1313614725
1313614725
1313614725
1313614725
1313614725
1313614725
1313614725

加锁虽然解决线程变不安全。但是执行效率也变低了,但是解决了根本问题。线程变为安全的了,

以上是关于设计模式。单例懒汉式(懒得让人觉得不够安全)的主要内容,如果未能解决你的问题,请参考以下文章

单例设计模式之懒汉式(线程安全)

单例模式之懒汉式

单例模式中的懒汉式以及线程安全性问题

2. 单例模式

单例模式——懒汉式饿汉式

线程安全的懒汉式单例设计模式