我在一些开源代码中发现了这段代码,我看到了一些异常的行为,这些代码将重新命名(名称已被更改)。我很确定它不是线程安全的,因为资源缺少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;
}编辑:使用Java 8
发布于 2016-03-24 02:41:42
不,这不安全--而是因为通常的双重检查锁问题,而不是因为第二个方法调用。具体来说,第二个线程可以看到一个非空的defaultResource,从而访问它,而不需要看过同步方法,因此不会在第一个线程上调用它之前建立一个边界;但这与内联的synchronized (this)块的问题完全相同。
你也是对的。如果字段是不稳定的,那么读取它就会建立一个发生-之前它的前写。
方法与Java模型(JMM)无关,除非它们是同步的,在这种情况下,它们的效果与synchronized块完全相同。与其考虑方法,我鼓励你考虑具体的行动:什么行动建立了一个发生-在边缘之前?在您提供的代码中,唯一能够提供发生的操作--在edge之前--是在同一监视器的上一次发布后(通过另一个线程退出该方法)获取this的监视器(通过输入同步方法)。因此,您必须问:我们是否可以在不执行这些操作的情况下读取非空defaultResource?答案是肯定的:实际上,在getSession开始时,defaultResource是非空的。因此,这些访问中的每一个都是数据竞赛。
https://stackoverflow.com/questions/36192187
复制相似问题