Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.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 - Fatal编程技术网

Java 使用本地变量的单例安全发布

Java 使用本地变量的单例安全发布,java,multithreading,Java,Multithreading,在阅读这篇文章时,我遇到了下面解释安全发布字段的代码 public class SafeLocalDCLFactory implements Factory { private volatile Singleton instance; @Override public Singleton getInstance() { Singleton res = instance; if (res == null) { synchronized (this) {

在阅读这篇文章时,我遇到了下面解释安全发布字段的代码

public class SafeLocalDCLFactory implements Factory {
  private volatile Singleton instance;

  @Override
  public Singleton getInstance() {
    Singleton res = instance;
    if (res == null) {
      synchronized (this) {
        res = instance;
        if (res == null) {
          res = new Singleton();
          instance = res;
        }
      }
    }
    return res;
  }
}
我的疑问是为什么我们需要在
getInstance()
中定义的本地var
res
易失性
DCL
是否足以保证
安全发布
?在此处定义本地var
res
,然后将其与
null
进行比较的目的到底是什么

编辑:本文解释了下面的内容,以证明使用本地var的必要性。但是我们如何保护自己不返回null呢

在这里引入局部变量是一个正确性修正,但仅限于 部分:在发布 Singleton实例,并读取其任何字段。我们只是 保护自己不返回“null”而不是Singleton 实例


它最小化了从易失性变量
实例
读取的次数。易失性变量访问比非易失性内存访问更昂贵,因为它通常涉及内存屏障。通过将其分配给临时变量,如果volatile变量已经初始化,则此代码只读取一次,而不是两次(一次检查,一次返回)。

F-Up问题:因为只有创建实例的null检查中的代码是同步的,
instance
是否可能在空检查和创建实例之间进行更改?场景:空检查为正;换线;空检查阳性;执行同步块并创建和保存isntance;换线;再次执行同步块并覆盖现有实例一旦一个线程进入同步块,另一个线程就无法进入。当初始化线程完成时,等待的线程将再次检查并查看实例是否已初始化。@JohannesH。在第二次线程更改中,它不会再次检查同步块内的空值吗?因为已经由第一个线程创建,所以它将为false?I。。。错过了第二张支票。是的,你们是对的。@BurakSerdar,谢谢,但在文章中提到使用本地变量的真正原因如下:“在这里引入局部变量是一个正确性修正,但只是部分修正:在发布Singleton实例和读取其任何字段之间仍然没有发生任何变化。我们只是保护自己不返回“null”,而不是单例实例?