【问题标题】:Synchronized block in Singleton Pattern (Java)单例模式(Java)中的同步块
【发布时间】:2020-04-17 08:39:59
【问题描述】:

我有一个关于我在 Wikipedia 上找到的线程安全单例模式的问题。

public final class Singleton {

    private static volatile Singleton instance = null;

    private Singleton() {}

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

        return instance;
    }
}

如果同步块没有同步,是否有可能2个线程同时创建2个对象?

我需要解释一下作业中“同步”的用法。

感谢和问候

【问题讨论】:

  • “线程安全”它并不完全安全。另一个线程可以在Singleton.class 上进行同步,并导致调用getInstance() 的线程无限期地阻塞。存在更简单、更健壮的方法(例如枚举或惰性持有者)。

标签: java multithreading synchronized volatile


【解决方案1】:

如果不同步,你确实可以让 2 个线程创建 2 个对象。

  • T1:检查实例是否为空 => 是! => 继续下一行
  • T2:检查实例是否为空 => 是! => 继续下一行
  • T1:创建对象
  • T2:创建对象

使用同步时,一次只能有1个线程进入同步阻塞。

  • T1:检查实例是否为空 => 是! => 继续下一行
  • T1:创建对象
  • T2:检查实例是否为空 => 否! => 跳过块

编辑:

值得注意的是,synchronized里面的null检查 块实际上非常重要 - 否则有可能 同时创建 2 个对象。 – 当中(以 cmets 计)

实现单例模式的另一种方法如下。 只有在应用程序启动后创建对象不是什么大问题时才使用此模式:

public final class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

【讨论】:

  • 值得注意的是,同步块内部的空检查实际上非常重要 - 否则也可以创建2个对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
  • 2015-04-09
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
相关资源
最近更新 更多