Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果初始值设定项代码在方法之间分割,双重检查锁惯用法是否安全?_Java_Multithreading_Locking_Synchronized - Fatal编程技术网

Java 如果初始值设定项代码在方法之间分割,双重检查锁惯用法是否安全?

Java 如果初始值设定项代码在方法之间分割,双重检查锁惯用法是否安全?,java,multithreading,locking,synchronized,Java,Multithreading,Locking,Synchronized,我在一些开源代码中发现了这段代码,我发现这些代码的行为异常,应该重命名为unnamed(名称已更改)。我很确定它不是线程安全的,因为资源缺少volatile关键字 另外,我也不确定这个成语在拆分时是否有效。这个习惯用法很脆弱,应该按照文档中的说明来实现,否则它可能不起作用(尽管他没有解释原因)。加上双写不闻写 除了缺少volatile之外,这段代码在多线程应用程序中如何失败 private Resource defaultResource = null; public Resource get

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

另外,我也不确定这个成语在拆分时是否有效。这个习惯用法很脆弱,应该按照文档中的说明来实现,否则它可能不起作用(尽管他没有解释原因)。加上双写不闻写

除了缺少volatile之外,这段代码在多线程应用程序中如何失败

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;
}
编辑:使用Java8是不安全的,但这是因为通常的双重检查锁问题,而不是因为第二个方法调用。具体地说,第二个线程可以看到一个非null的
defaultResource
,因此在没有看到同步方法的情况下访问它,从而在第一个线程上调用它时不会建立一个before边;但是如果是一个内联的
synchronized(this)
块,那么问题就完全一样了

你也说得对。如果该字段是易失性的,则读取该字段将建立一个先前写入的事件


方法与Java内存模型(JMM)没有关系,除非它们是同步的,在这种情况下,它们的效果与
同步的
块完全相同。与其思考方法,不如鼓励你们思考具体的行动:什么行动建立了先发制人的优势?在您提供的代码中,唯一可以提供before edge的操作是在同一监视器的上一版本(通过另一个线程退出该方法)之后获取
的监视器(通过输入同步方法)。因此,您必须问:有没有任何方法可以在不执行这些操作的情况下读取非null的
defaultResource
?答案是肯定的:事实上,只要
defaultResource
getSession
开始时不为null,就可以执行该操作。因此,这些访问中的每一个都是一场数据竞赛。

针对哪个版本的Java?不管怎样,我认为它是安全的。编译器无法对其重新排序,该方法是
synchronized
@ElliottFrisch java 8。事实上,该方法可以很容易地由JIT内联,因此您真正拥有的是一个
synchronized(this){}
包装器,它返回到原始问题。