Kotlin 使用 object 建立獨體模式(Singleton)是 Thread-Safe 的

在 Java 裡面使用 Singleton 模式的時候,為了要保證 Thread-Safe,必須宣告 synchronized:

public class Singleton {
    private Singleton() {}
    private static volatile Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return sInstance;
    }
}

但是在 Kotlin 裡面,不需要特別宣告:

object Singleton

看編譯過後的程式碼:

public final class com/cathay/integrationplatform/Singleton {


  // access flags 0x2
  private <init>()V
   L0
    LINENUMBER 3 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/cathay/integrationplatform/Singleton; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x19
  public final static Lcom/cathay/integrationplatform/Singleton; INSTANCE

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 3 L0
    NEW com/cathay/integrationplatform/Singleton
    DUP
    INVOKESPECIAL com/cathay/integrationplatform/Singleton.<init> ()V
    ASTORE 0
    ALOAD 0
    PUTSTATIC com/cathay/integrationplatform/Singleton.INSTANCE : Lcom/cathay/integrationplatform/Singleton;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  @Lkotlin/Metadata;(mv={1, 1, 15}, bv={1, 0, 3}, k=1, d1={"\u0000\u000c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\u0008\u00c6\u0002\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002\u00a8\u0006\u0003"}, d2={"Lcom/cathay/integrationplatform/Singleton;", "", "()V", "integrationplatform"})
  // compiled from: Singleton.kt
}

根據參考資料[2]的解釋:

Static initialization block is exeucted when a class is loaded by classloader (in class loader's native implementation). Classloader will never load a class concurrently so static init block is always "synchonized". This is true not just for Kotlin but for any JVM language. From this point of view the answer is "yes". However there could be multple class loaders present so you can load a class several times and get several singleton's instances. This is not bug but a feature

原來是因為 Classloader 只會載入一次 static 的 init 區塊,所以達到 Singleton 的效果。

參考資料:

  1. https://stackoverflow.com/questions/30179793/are-kotlins-singletons-thread-safe
  2. https://medium.com/@oznusem/the-right-way-to-write-a-singleton-when-developing-for-android-or-any-multithreaded-environment-79782dd48f95

results matching ""

    No results matching ""