首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果初始化程序代码在方法之间被分割,那么双重检查的锁习语是否安全?

如果初始化程序代码在方法之间被分割,那么双重检查的锁习语是否安全?
EN

Stack Overflow用户
提问于 2016-03-24 02:20:08
回答 1查看 38关注 0票数 2

我在一些开源代码中发现了这段代码,我看到了一些异常的行为,这些代码将重新命名(名称已被更改)。我很确定它不是线程安全的,因为资源缺少volatile关键字。

另外,我也不确定这个成语在分开时是否行得通。乔希·布洛赫声称这个成语是脆弱的,应该按照文档来实现,否则它可能行不通(尽管他没有解释原因)。另外,双写不闻写。

除了这里缺少易失性之外,这段代码在多线程应用程序中怎么会失败呢?

代码语言:javascript
复制
private Resource defaultResource = null;

public Resource getSession() {
    if (defaultResource == null) {
        defaultResource = initializeResource();
    }
    return defaultResource;
}

private synchronized Resource initializeResource() {
    if (defaultResource == null) {
        defaultResource = getResourceBuilder().build();
    }
    return defaultResource;
}

编辑:使用Java 8

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-24 02:41:42

不,这不安全--而是因为通常的双重检查锁问题,而不是因为第二个方法调用。具体来说,第二个线程可以看到一个非空的defaultResource,从而访问它,而不需要看过同步方法,因此不会在第一个线程上调用它之前建立一个边界;但这与内联的synchronized (this)块的问题完全相同。

你也是对的。如果字段是不稳定的,那么读取它就会建立一个发生-之前它的前写。

方法与Java模型(JMM)无关,除非它们是同步的,在这种情况下,它们的效果与synchronized块完全相同。与其考虑方法,我鼓励你考虑具体的行动:什么行动建立了一个发生-在边缘之前?在您提供的代码中,唯一能够提供发生的操作--在edge之前--是在同一监视器的上一次发布后(通过另一个线程退出该方法)获取this的监视器(通过输入同步方法)。因此,您必须问:我们是否可以在不执行这些操作的情况下读取非空defaultResource?答案是肯定的:实际上,在getSession开始时,defaultResource是非空的。因此,这些访问中的每一个都是数据竞赛。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36192187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档