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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/successA/article/details/79269456

代码段

   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 不为空,那么初始化一定完成。


总结

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



猜你喜欢

转载自blog.csdn.net/successA/article/details/79269456