Java面试题:不使用锁如何实现线程安全的单例?

Java面试题:不使用锁如何实现线程安全的单例?。小编来告诉你更多相关信息。Java面试题为大家介绍的是Java面试题的内容,接下来带大家一起了解。面试官问:不使用锁,如何实现线程安全的单例?如果不能使用syn...

Java面试题:不使用锁如何实现线程安全的单例?。小编来告诉你更多相关信息。

Java面试题

为大家介绍的是Java面试题的内容,接下来带大家一起了解。

面试官问:不使用锁,如何实现线程安全的单例?

如果不能使用synchronized和lock的话,想要实现单例可以通过饿汉模式枚举、以及静态内部类的方式实现。

Java面试题:不使用锁如何实现线程安全的单例?-图1

饿汉:

其实都是通过定义静态的成员变量,以保证instance可以在类初始化的时候被实例化。

// 单例模式// 饿汉式(静态变量)class Singleton {    // 1. 构造器私有化    private Singleton() {}    // 2. 本类内部创建对象实例    private final static Singleton instance = new Singleton(); // 静态变量    // 3. 提供一个公有的静态方法,返回实例对象    public static Singleton getInstance() {        return instance;    }}

但是,如果从始至终未使用过这个实例,会造成内存浪费

静态内部类

这种方式和饿汉方式只有细微差别,只是做法上稍微优雅一点。

// 静态内部类实现class Singleton {    // 构造器私有化    private Singleton() {}    // 写一个静态内部类,含一个静态属性Singleton    private static class SingletonHolder {        private static final Singleton INSTANCE = new Singleton();    }    // 提供一个静态的公有方法,直接返回SingleInstance.INSTANCE    public static Singleton getInstance() {        return SingletonHolder.INSTANCE;    }}

原理和饿汉一样。这种方式是Singleton类被装载了,INSTANCE 对象不一定被初始化。

因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance

枚举

借助了 JDK1.5 中添加的枚举来实现单例模式,不仅避免了多线程同步问题,而且还防止反序列化重新创建新的对象

// 枚举实现单例enum Singleton {    INSTANCE; // 属性}

其实,如果把枚举类进行反编译,你会发现他也是使用了static final来修饰每一个枚举项。

final class Singleton extends Enum{    public static final Singleton INSTANCE;    private static final Singleton $VALUES[];    public static Singleton[] values()    {        return (Singleton[])$VALUES.clone();    }    public static Singleton valueOf(String name)    {        return (Singleton)Enum.valueOf(cn/itsource/logweb/utils/Singleton, name);    }    private Singleton(String s, int i)    {        super(s, i);    }    static     {        INSTANCE = new Singleton(\"INSTANCE\", 0);        $VALUES = (new Singleton[] {            INSTANCE        });    }}

其实,上面三种方式,都是依赖静态数据在类初始化的过程中被实例化这一机制的。

Java面试题:不使用锁如何实现线程安全的单例?。小编来告诉你更多相关信息。

Java面试题

但是,如果真要较真的话,ClassLoader的loadClass方法在加载类的时候使用了synchronized关键字。

也正是因为这样, 除非被重写,这个方法默认在整个装载过程中都是同步的(线程安全的)。

那么,除了上面这三种,还有一种无锁的实现方式,那就是CAS。

public class Singleton {    // 使用了 AtomicReference 封装单例对象     private static final AtomicReference INSTANCE = new AtomicReference();     private Singleton() {}    public static Singleton getInstance() {        while (true) {            // 使用 AtomicReference.get 获取            Singleton singleton = INSTANCE.get();            if (null != singleton) {                return singleton;            }            // 使用 CAS 乐观锁进行非阻塞更新            singleton = new Singleton();            if (INSTANCE.compareAndSet(null, singleton)) {                return singleton;            }        }    }}

用CAS的好处在于不需要使用传统的锁机制来保证线程安全。

但是我们的实现方式中,用了一个while循环一直在进行重试,所以,这种方式有一个比较大的缺点在于,如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。

以上是网关于Java面试题 和 不使用锁如何实现线程安全的单例的技术经验小知识,以上内容供大家学习了解!

阅读前请先查看【免责声明】本文内容由互联网用户自发贡献,该文观点仅代表作者本人,本站仅供展示。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 1217266901@qq.com 举报,一经查实,本站将立刻删除。 转载请注明出处:https://www.jingfakeji.com/tech/33367.html

上一篇 2023年11月02日 21:50
下一篇 2023年11月02日 21:51

相关推荐

  • 实际工作中哪里用到了自定义注解的方法

    实际工作中哪里用到了自定义注解的方法。小编来告诉你更多相关信息。实际工作中哪里用到了自定义注解的方法小编为大家解答实际工作中哪里用到了自定义注解的方法的相关知识,下面小编为您详细解答自定义注解可以标...

    2024年02月05日
    4
  • SpringBean的生命周期

    SpringBean的生命周期。小编来告诉你更多相关信息。Spring文章摘要:Spring方面的介绍,具体详情如下:既然聊到SpringBean的生命周期,首先,我们要知道的是JavaB...

    2024年01月10日
    11
  • SpringAOP/IOC实现原理

    SpringAOP/IOC实现原理。小编来告诉你更多相关信息。Spring正文核心介绍:Spring的内容,一起跟随小编看看吧!AOP什么是AOP通俗的讲就是当你想要实现对象增强,就可以使用AOP...

    2024年01月10日
    9
  • JVM、JDK、JRE的区别

    JVM、JDK、JRE的区别。小编来告诉你更多相关信息。JVM、JDK、JRE的区别今日重点为您介绍JVM、JDK、JRE的区别方面的介绍,接下来带大家一起了解。它们之间的区别如下:JVM是...

    2024年01月10日
    10
  • JVM解释和编译指南

    JVM解释和编译指南。小编来告诉你更多相关信息。JVM解释和编译指南为关注网的网友们详解JVM解释和编译指南的相关介绍,接下来分享详细内容。Java是一种跨平台的编程语言。程序源代...

    2023年11月11日
    7
  • Redis锁被别人释放解决办法

    Redis锁被别人释放解决办法。小编来告诉你更多相关信息。Redis锁被别人释放解决办法一篇方法教程,与您分享Redis锁被别人释放解决办法的相关经验,接下来一起来看看吧。什么是分布式锁?要介...

    2023年11月06日
    9

联系我们

在线咨询: QQ交谈

邮箱:1217266901@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信