有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

既不使用volatile也不使用局部变量的java双重检查锁定

在不考虑这一点之前,可以在不使用volatile的情况下执行双重检查锁定,见下文。我建议在这个基础上做一个改变,去掉局部变量

以下是Shipilev的双重检查锁定的正确实现:

public class FinalWrapperFactory {
  private FinalWrapper wrapper;

  public Singleton get() {
    FinalWrapper w = wrapper;
    if (w == null) { // check 1
      synchronized(this) {
        w = wrapper;
        if (w == null) { // check2
          w = new FinalWrapper(new Singleton());
          wrapper = w;
        }
      }
    }
    return w.instance;
  }

  private static class FinalWrapper {
    public final Singleton instance;
    public FinalWrapper(Singleton instance) {
      this.instance = instance;
    }
  }
}

我想知道是否有可能去掉局部变量^{

public class FinalWrapperFactory {
  private FinalWrapper wrapper; //same as example above

  public Singleton get() {
    if (wrapper == null) { // read 1
      synchronized(this) {
        if (wrapper == null) { // read 2
          wrapper = new FinalWrapper(new Singleton());
          return wrapper.instance; // read 3
        } else {
          return wrapper.instance; // read 4 
        }
      }
    } else {
      return wrapper.instance; // read 5 (last read). Can this be reordered?
    }
  }
}

JLS 817.4.8. Executions and Causality Requirements中写着:

Informally, we allow an action to be committed early if we know that the action can occur without assuming some data race occurs.

这里的一个大问题是,最后一次读取(读取5)是否可以重新排序,这样我们就可以在读取1中看到一个非空的包装,而在最后一次读取中仍然可以看到一个空的包装。在线程第一次调用get()时,不应允许发生这种情况,因为最后一次读取的唯一方式是数据竞争,JMM将禁止重新排序

get()的后续调用中,可以进行重新排序,但这并不重要,因为包装器无论如何都应该是可见的


共 (0) 个答案