双重检查锁定与单例

栏目: Java · 发布时间: 6年前

内容简介:对于单例模式,相信大多数人都可以写出好几种实现方法,懒汉,饿汉等等,然而小小单例真要写好,写的完全正确也并非易事。下面是我们经常使用的一种单例的实现,也就是双重检查所的实现方案。让我们来看一下这个代码是如何工作的:首先当一个线程发出请求后,会先检查instance是否为null,如果不是则直接返回其内容,这样避免了进入synchronized块所需要花费的资源。其次,如果两个线程同时进入了第一个if判断,那么他们也必须按照顺序执行 synchronized 块中的代码,第一个进入代码块的线程会创建一个新的

对于单例模式,相信大多数人都可以写出好几种实现方法,懒汉,饿汉等等,然而小小单例真要写好,写的完全正确也并非易事。

双重检查锁的单例

下面是我们经常使用的一种单例的实现,也就是双重检查所的实现方案。

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        
    }

    public Singleton getInstance() {
        if (null == instance) {
            synchronized (Singleton.class) {
                if (null == instance) {
                    instance = new Singleton();   // error
                }
            }
        }
        return uniqueSingleton;
    }
}

让我们来看一下这个代码是如何工作的:首先当一个线程发出请求后,会先检查instance是否为null,如果不是则直接返回其内容,这样避免了进入synchronized块所需要花费的资源。其次,如果两个线程同时进入了第一个if判断,那么他们也必须按照顺序执行 synchronized 块中的代码,第一个进入代码块的线程会创建一个新的 Singleton 实例,而后续的线程则因为无法通过if判断,而不会创建多余的实例。

但还有一个问题,在有些情况下,通过这种方式拿到的Singleton对象,可能是错误的 。

回顾我们new对象的3个步骤

  • 1,分配内存空间

  • 2,初始化对象

  • 3,将对象指向刚分配的内存空间

但jvm在指令优化时,会出现步骤2和3对调的情况,比如线程1在经过俩层为 null 判断后,进入 new 的动作,在还没有初始化对象时,就返加了地址值,线程2在第一个为 null 判断时,因为对象已经不为空,那么就直接返回了对象。然而当线程2打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。

解决方案

对于上面的问题,有两种解决方案

1,使用 volatile 关键词主要可以保证代码的执行顺序不受 jvm 重 排序 影响。

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
    }

    public Singleton getInstance() {
        if (null == instance) {
            synchronized (Singleton.class) {
                if (null == instance) {
                    instance = new Singleton();   // error
                }
            }
        }
        return instance;
    }
}

2,通过内部类实现多线程环境中的单例模式。

public class Singleton {        
    
    private Singleton() {       
    }        
    
    private static class SingletonContainer {        
        private static Singleton instance = new Singleton();        
    }        
    
    public static Singleton getInstance() {        
        return SingletonContainer.instance;        
    }        
}

双重检查锁定与单例


以上所述就是小编给大家介绍的《双重检查锁定与单例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning jQuery

Learning jQuery

Jonathan Chaffer、Karl Swedberg / Packt Publishing / 2007-7-7 / GBP 24.99

jQuery is a powerful JavaScript library that can enhance your websites regardless of your background. In this book, creators of the popular jQuery learning resource, learningquery.com, share the......一起来看看 《Learning jQuery》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具