当前位置: 首页 > 知识库问答 >
问题:

kotlin中的lateinit、lazy和singleton模式

史鹏云
2023-03-14
public class Manager {
  private static volatile Manager Instance = null;
  private static final Object InstanceLock = new Object();
  private Manager(Object1 object1, Object2 object2, Object3 object3){//...};
  public static boolean isInitialized(){
    synchronized(InstanceLock){
        return Instance == null;
    }
  }
  public static void initialize(Object1 object1, Object2 object2, Object3 object3){
      if(Instance == null){
         synchronized(InstanceLock){
             if(Instance == null){Instance = new Manager(object1, object2, object3};
         }
      }
  }
  public static getInstance(){
       Precondition.checkNotNull(Instance, msg...);
       return Instance;
  }
}

另外,我将.kt反编译回Java。在companion类中,我得到以下代码

public static final class Companion {
  @Nullable
  public final Manager getInstance() {
     return Manager.instance;
  }

  private final void setInstance(Manager var1) {
     Manager.instance = var1;
  }

  private final Object getInstanceLock() {
     return Manager.InstanceLock;
  }

  public final boolean isInitialized() {
     Object var1 = Manager.Companion.getInstanceLock();
     synchronized(var1){}

     boolean var4;
     try {
        var4 = Manager.Companion.getInstance() == null;
     } finally {
        ;
     }

     return var4;
  }

  public final void initialize(@NotNull String string1, @NotNull String string2) {
     Intrinsics.checkParameterIsNotNull(string1, "string1");
     Intrinsics.checkParameterIsNotNull(string2, "string2");
     if (((Manager.Companion)this).getInstance() == null) {
        Object var3 = ((Manager.Companion)this).getInstanceLock();
        synchronized(var3){}

        try {
           if (Manager.Companion.getInstance() == null) {
              Manager.Companion.setInstance(new Manager(string1, string2, (DefaultConstructorMarker)null));
           }

           Unit var5 = Unit.INSTANCE;
        } finally {
           ;
        }
     }

  }

  private Companion() {
  }

  // $FF: synthetic method
  public Companion(DefaultConstructorMarker $constructor_marker) {
     this();
  }

}

1)如何通过在kotlin同伴对象中使用lateinit或lazy来实现线程安全、单例?正如我所看到的,反编译的java代码在initialize函数中有一个synchronized调用,但在synchronize正文中没有。

共有1个答案

卞云瀚
2023-03-14

第一个答案没有解决同步问题,顺便说一句,它仍然是一个不被重视的复杂性。仍然有一吨人跑来跑去,说简单地做双重检查锁定。但是有一些非常令人信服的论点表明DCL并不总是有效的。

有趣的是,我最近也遇到了同样的问题,并发现了这篇文章。虽然我第一次发现它时不喜欢它,但我重新审视了几次,并对它感到热身,很大程度上是因为:

  • 作者从Kotlin stdlib获得了代码
  • 结果是一个参数化的机制,虽然有点难看,但它提供了重用,这是非常引人注目的
    null
 类似资料:
  • 我正在努力把这个改型班翻译成科特林。它基本上是一个作为客户机工作的单例,我不确定我的Kotlin实现。UserAPI和ProfileAPI只是接口。 这是我的Kotlin实现。正如我所理解的,当类实例化时,init块将首先执行。 但有些事情告诉我,这不是正确的方法,或者可以做得更好。这里有什么我可以改进的吗? 更新!!! 可以吗?

  • 我有这样的代码: 当我们没有任何其他getInstance的静态方法时,是否初始化了此单例惰性?据我所知,类只在某些情况下初始化,比如: 类的实例是使用new()关键字或使用类的反射创建的。forName(),它可能在Java中引发ClassNotFoundException (Surce:http://javarevisited.blogspot.com/2012/07/when-class-l

  • 惰性初始化 是一个接受lambda并返回实例的函数,该实例可以作为实现lazy属性的委托:对的第一次调用执行传递给的lambda并记住结果,随后对的调用只返回记住的结果。 例 修饰符只能用于在类主体中声明的var属性(而不是在主构造函数中),并且只能在属性没有自定义getter或setter时使用。属性的类型必须是非空的,并且不能是基元类型。 那么,既然这两个选项都能解决同样的问题,如何在这两个选

  • 问题内容: 默认情况下,我们在Spring容器中将bean作为单例,如果我们有一个基于Spring框架的Web应用程序,那么在这种情况下,我们真的需要实现Singleton设计模式来保存全局数据,而不仅仅是通过spring创建bean 。 问题答案: Spring中的单例豆和单例模式有很大不同。Singleton模式表示,每个类加载器将只创建一个特定类的一个实例。 Spring单例的范围描述为“每

  • 我有一个DAO类,它在内部查询Oracle序列的next_val。 由于此序列不绑定到任何实体,只是查询内部逻辑的值,因此每次在DAO上调用方法时,我都会创建本机查询,如下所示: 由于每次调用该方法时都要创建查询,因此我想重构该方法,以便在定义为Springbean的单例中创建本机查询,以便只在第一次调用我的时创建查询。 这样做有什么缺点吗?Hibernate会话会给这种方法带来问题吗?

  • 在kotlin中,我们可以使用以下两种方法和 什么时候使用哪种方法,这两种方法实际上是在下面进行的。哪一种方法是最好的?