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

没有最终修饰符的按需初始化持有人惯用语线程安全吗?

西门嘉石
2023-03-14
问题内容

我有一种直觉,即使用Holder惯用法而不将Holder字段声明为final并不是线程安全的(由于Java中不变性的工作方式)。有人可以确认(希望有一些消息来源)吗?

public class Something {
    private long answer = 1;

    private Something() {
         answer += 10;
         answer += 10;
    }

    public int getAnswer() {
      return answer;
    }

    private static class LazyHolder {
        // notice no final
        private static Something INSTANCE = new Something();
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }

}

编辑:我绝对希望来源声明,而不仅仅是“它起作用”这样的断言-请解释/证明它是安全的

EDIT2:进行一点点修改以使我的观点更清楚-是否可以确定getAnswer()方法将返回21,而不管调用线程如何?


问题答案:

在类的初始化程序保证,如果静态字段的值是使用静态初始化(即设置static variable = someValue;),该值是对所有线程可见:

10-如果初始化程序的执行正常完成,则 _ 获取LC,将C的Class对象标记为完全初始化,通知所有等待的线程,释放LC_
,然后正常完成此过程。

关于您的编辑,让我们想象一个情况,从挂钟的角度来看,有两个线程T1和T2以该顺序执行:

  • T1: Something s = Something.getInstance();
  • T2: Something s = Something.getInstance(); i = s.getAnswer();

然后您有:

  • T1获取LC,T1运行Something INSTANCE = new Something();,初始化answer,T1发布LC
  • T2试图获取LC,但是已经被T1锁定=>等待。当T1释放LC时,T2获取LC,INSTANCE然后读取answer

因此answer,由于LC锁定,您可以看到对to的写入和读取之间具有适当的事前发生关系。



 类似资料:
  • 问题内容: 我有两个版本的“按需初始化持有人惯用语”: http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh 两者之间的主要区别在于,第一个声明为 私有 ,而第二个声明为 公

  • 问题内容: 我试图简单地测试JLS保证的最终字段的初始化安全性。这是我写的论文。但是,根据我当前的代码,我无法使其失败。有人可以告诉我我做错了什么吗,或者这只是我必须一遍又一遍然后看到失败的时机而已? 这是我的代码: 我的线程正在这样调用它: 我已经多次运行过这种情况。我当前的循环产生了10,000个线程,但是我已经完成了1000、100000,甚至一百万个线程。仍然没有失败。我总是看到3和4这两

  • 问题内容: 我试图基于初始化按需持有人习惯用法创建一个线程安全的单例类。这是我的代码 我的期望是以线程安全的方式初始化ExecutorService,并且那里只有一个实例(静态)。 这段代码是实现了这一目标-还是需要任何更改? 问题答案: 根据SEI 指南,您的方法很好。 但是,由于我们有枚举,因此可以使用枚举的简单方法: 而且,如果您想变得真正聪明,还可以定义枚举实现的接口。因为这样您以后可以

  • 我得到的是它们是线程安全的。 杰里米·曼森博客的片段- 因为this引用存储在lastconstructed中“,因此转义构造函数 请建议。

  • 问题内容: 我对Swift类有疑问。我有一个UITableViewController类和UITableViewCell类的快捷文件。我的问题是UITableViewCell类和插座。此类存在错误 类别“ HomeCell”没有初始化程序 ,并且我不理解此问题。 感谢您的回复。 问题答案: 您必须使用隐式展开的可选变量,以便Swift可以在初始化阶段处理循环依赖关系(在这种情况下,UI组件的父级<

  • 问题内容: 我正在使用静态代码块来初始化我拥有的注册表中的某些控制器。因此,我的问题是,我可以保证在首次加载该类时,该静态代码块仅被绝对调用一次吗?我知道我不能保证何时将调用此代码块,我猜是在Classloader首次加载时。我意识到我可以在静态代码块中的类上进行同步,但是我猜这实际上是怎么回事? 简单的代码示例将是; 还是我应该这样做? 问题答案: 是的,Java静态初始化器是线程安全的(使用第