工作深度总结——双重锁定实现单例

Posted 喵喵7781

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工作深度总结——双重锁定实现单例相关的知识,希望对你有一定的参考价值。

代码段

 

   private static volatile OSSClient ossClient;

    private static OSSClient getOssClient() 
        if (ossClient == null) 
            synchronized (OSSClient.class) 
                if (ossClient == null) 
                    ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
                    Runtime.getRuntime().addShutdownHook(new Thread(() -> ossClient.shutdown()));
                
            
        
        return ossClient;
    


关键代码解析

 

原子性

 synchronized 确保当前只有一个线程实例化oss客户端

可见性

 volatitle 全局共享变量,在Java5之后,遵循happens-before原则,一旦被改变,立刻写入内存,写优先于读。

有序性

synchronized 保证了线程的有序性

钩子

 已经初始化,但是并不启动的线程,jvm退出之前,进行ossClient的关闭。

 

代码逻辑解析

 首先判断ossClient是否为空,如果不为空,就直接返回;如果为空,就先锁定当前的类,允许一个线程进入。

然后再次判断ossClient是否被初始化。如果没有被初始化,就new 一个ossClient;如果被初始化,就直接返回实例化对象。

 如果没有通过volatitle 修饰,可能会报错,因为JVM主要进行三个操作:1.给 ossClient 分配内存 2.调用 Singleton 的构造函数来初始化成员变量

3. 将ossClient对象指向分配的内存空间(执行完这步ossClient就为非 null 了),2和3的操作顺序未知,如果先进行3,然后再进行2操作,ossClient不为空,

2还没有完成,返回就会报错。

 Java5之后,通过volatitle修饰,保证写优先于读,所以如果判断ossClient 不为空,那么初始化一定完成。

 

总结

编写优秀的代码,就像欣赏一首美妙的歌曲,美好的事物,谁不喜欢呢~

 

 

 

以上是关于工作深度总结——双重锁定实现单例的主要内容,如果未能解决你的问题,请参考以下文章

单例模式双重检查锁定与延迟初始化你不得不知道的底层原理

单例模式双重检查锁定与延迟初始化你不得不知道的底层原理

单例模式中的volatile关键字

双重检查锁定和单例模式

单例模式的优化-双重锁定

单例模式的优化-双重锁定