当前位置: 首页 > 面试题库 >

使用双重锁定时使单例实例具有可变性有什么意义?

陶沛
2023-03-14
问题内容

private volatile static Singleton uniqueInstance

在使用双重锁定方法进行同步的单例中,为什么将单个实例声明为volatile?是否可以在不声明为易失性的情况下实现相同的功能?


问题答案:

如果没有volatile代码,则无法在多个线程中正常工作。

从Wikipedia的双重检查锁定:

从J2SE
5.0开始,此问题已得到解决。现在,volatile关键字可确保多个线程正确处理单例实例。在“双重检查锁定已损坏”声明中描述了这一新用法:

// Works with acquire/release semantics for volatile
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        Helper result = helper;
        if (result == null) {
            synchronized(this) {
                result = helper;
                if (result == null) {
                    helper = result = new Helper();
                }
            }
        }
        return result;
    }

    // other functions and members...
}

通常,如果可能,应该避免仔细检查锁定,因为很难正确,如果错误,则很难找到错误。请尝试使用以下更简单的方法:

如果helper对象是静态的(每个类加载器一个),则替代方法是按需初始化持有人惯用语

// Correct lazy initialization in Java 
@ThreadSafe
class Foo {
    private static class HelperHolder {
       public static Helper helper = new Helper();
    }

    public static Helper getHelper() {
        return HelperHolder.helper;
    }
}


 类似资料:
  • 这是我为单例模式的自定义类。在这段代码中,我使用双重检查锁定,如下所示。当我在一些源代码上读到许多帖子时,他们说双重检查很有用,因为它可以防止两个并发线程同时运行,从而产生两个不同的对象。 我还是不太懂上面的代码。当实例为null时,如果两个线程一起运行同一行代码,问题是什么? 当它出现时。两个线程都将看到对象为null。然后两者同步。然后,他们再次检查,仍然看到它为空。并创建两个不同的对象。哎呀

  • 问题内容: 对于2015年9月,以下是在Swift中制作单例的确切方法: 然后在其他地方… 没问题。 然后,您可以在整个项目范围内简单地执行以下操作: 传统习语: Model.shared.blah()…在代码库中到处可见 “我的”成语: model.blah()…在代码库中到处可见 因此,这导致一切看上去都很漂亮: (在你的项目中,那些“单变量”将是一些事情,如,,,或任何情况下可能会在您的项目

  • 问题内容: 这是我写的三个类: Tester类的main方法的输出为: 为什么sx返回0而不是1?由于不是Rectangle变量的当前实例,并且该类也声明了相同的实例变量,或者Rectangle类中的变量没有像对getX()一样覆盖Shape类中的先前公共x变量。矩形类中的方法因此返回1? 同样作为一般规则,超类仅在其子类中也声明了其子类方法时才可以访问其子类的实现?这是因为编译器会看到“ Sha

  • 我读了很多关于应该使用的案例。 我读过的许多页面都说不应该用于私有实例变量,而应该由getters返回。 我认为将私有实例变量作为可选变量仍然是有用的。如果有人查看我的代码,他们可以看到一个值可以是空的,而不必检查留档是否可以返回空。 在Scala中,null从未使用过,它只是用于与Java的互操作性。如果值可以为null,建议始终使用可选值。这种方法对我来说更有意义。 这里有一页提到了它: ht

  • 问题内容: 在阅读有关同步的内容时,我遇到了“监视器模式”以封装可变状态。 以下是示例代码 } 用私有锁代替固有锁更好吗? 问题答案: 是的-这意味着您可以看到 所有可能获得该锁的代码 (不考虑反射的可能性)。 如果您锁定(这是我假设您通过“固有锁定”所指的),那么其他代码可以做到: 该代码可能与自己的代码相距很远,并且可能调用其他方法,这些方法又将监视器带走。在这里很容易陷入死锁领域,因为您不容

  • 问题内容: 为什么在类中声明的变量具有默认值,但是在方法内部声明的变量(称为“局部变量”)在Java中没有默认值? 例如 在上面的示例中,变量的默认值为0,但是变量给出了可能尚未初始化的错误。 问题答案: 所有成员变量都必须加载到堆中,因此在创建类的实例时必须使用默认值进行初始化。对于局部变量,它们不会被加载到堆中,直到在Java7之前被使用,它们才会存储在堆栈中,因此我们需要显式初始化它们。现在