资讯专栏INFORMATION COLUMN

单例模式的双重判否

anonymoussf / 974人阅读

摘要:概述在单例模式的懒汉模式中,方法通常是采用如下方式写的这样的写法在多线程的情况下有可能造成不同的线程都实例化了一个对象出来,所以该写法是线程不安全的。全部代码这是普通模式这是同步模式这是双重判否模式

概述

在单例模式的懒汉模式中,getInstance方法通常是采用如下方式写的:

public static STest getInstance(){
    if(sTest==null){
        sTest = new STest();
    }
    return sTest;
}

这样的写法在多线程的情况下有可能造成不同的线程都实例化了一个对象出来,所以该写法是线程不安全的。那么怎么办呢?

加锁的解决方法

首先,自然想到既然线程不安全的原因是多个线程可能同时执行方法,那么加锁肯定是一个不错的解决方案,

public static synchronized STest getInstance2(){
    if(sTest==null){
        sTest = new STest();
    }
    return sTest;
}

这样在一定程度上的确能保证多线程下的安全,但是如果多个线程都要调用该方法,然后都要等待排在前面的线程去判断sTest对象是否为空,在效率上落了下乘。所以为了兼顾安全和效率,有了双重判否的解决方式。

双重判否

双重判否并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

全部代码
package Test0328;

/**
 * Created by Cesar on 2016/3/28.
 */
public class STest {
    private static volatile STest sTest;

    private STest() {
    }

    /**
     * 这是普通模式
     *
     * @return
     */
    public static STest getInstance() {
        if (sTest == null) {
            sTest = new STest();
        }
        return sTest;
    }

    /**
     * 这是同步模式
     *
     * @return
     */
    public static synchronized STest getInstance2() {
        if (sTest == null) {
            sTest = new STest();
        }
        return sTest;
    }

    /**
     * 这是双重判否模式
     *
     * @return
     */
    public static STest getInstance1() {
        if (sTest == null) {
            synchronized (STest.class) {
                if (sTest == null) {
                    sTest = new STest();
                }
            }
        }
        return sTest;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65672.html

相关文章

  • Java 双重加锁单例与 java 内存重排序特性

    摘要:关于对于重排序的讲解,强烈推荐阅读程晓明写的深入理解内存模型二重排序。语义语义单线程下,为了优化可以对操作进行重排序。编译器和处理器为单个线程实现了语义,但对于多线程并不实现语义。双重加载的单例模式分析即双重检查加锁。 版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009231182 1. 引言 在开始分析双重加锁单...

    HackerShell 评论0 收藏0
  • 深入理解单例模式

    摘要:总结我们主要介绍到了以下几种方式实现单例模式饿汉方式线程安全懒汉式非线程安全和关键字线程安全版本懒汉式双重检查加锁版本枚举方式参考设计模式中文版第二版设计模式深入理解单例模式我是一个以架构师为年之内目标的小小白。 初遇设计模式在上个寒假,当时把每个设计模式过了一遍,对设计模式有了一个最初级的了解。这个学期借了几本设计模式的书籍看,听了老师的设计模式课,对设计模式算是有个更进一步的认识。...

    FuisonDesign 评论0 收藏0
  • 设计模式系列之单例模式

    摘要:下面我们来看看看中的单例模式,中使用的是单例注册表的特殊方式实现的单例模式,所以说模式是死的,需要灵活得运用。 本文循序渐进介绍单例模式的几种实现方式,以及Jdk中使用到单例模式的例子,以及sring框架中使用到的单例模式例子。 饿汉式 package signgleton; /** * 单例模式简单的实现 */ public class Singleton { priv...

    Jason 评论0 收藏0
  • #yyds干货盘点#设计模式之【单例模式

    摘要:枚举推荐优点懒加载,线程安全,效率高,大牛推荐作者推荐总结关于单例模式的实现方式,首推的就是枚举,其次是懒汉模式双重检查,最后是静态内部类 作者:汤圆个人博客:javalover.cc前言有时候我们的类并不需要很多个实例,在程序运行期间,可能只需要一个实例就够了,多了反而会出现数据不一致的问题;这时候我们就可以...

    sourcenode 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<