Skip to content

Instantly share code, notes, and snippets.

@Razeeman
Last active November 9, 2023 19:23
Show Gist options
  • Save Razeeman/0310c2d455c76712eb451bca2c533ac8 to your computer and use it in GitHub Desktop.
Save Razeeman/0310c2d455c76712eb451bca2c533ac8 to your computer and use it in GitHub Desktop.
Thread safe singleton implementations in java and kotlin.

Java

Not thread safe.

class SimpleSingleton {
    private static SimpleSingleton sInstance;
  
    private SimpleSingleton() {}
  
    public static SimpleSingleton getInstance() {
        if (sInstance == null) {
            sInstance = new SimpleSingleton();
        }
        return sInstance;
    }
}

Thread safe, but not lazy.

class SimpleSingleton {
    private static SimpleSingleton sInstance = new SimpleSingleton();
  
    private SimpleSingleton() {}
  
    public static SimpleSingleton getInstance() {
        return sInstance;
    }
}

Thread safe(?) and lazy.

public class Singleton {
    private static final Object LOCK = new Object();
    private static Singleton sInstance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (sInstance == null) {
            syncronized(LOCK) {
                sInstance = new Singleton();
            }
        }
        return sInstance;
    }
}

Thread safe and lazy, but wasteful.

public class Singleton {
    private static Singleton sInstance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (sInstance == null) {
            sInstance = new Singleton();
        }
        return sInstance;
    }
}

Thread safe, but lazy at the class initialization not on INSTANCE.

public enum Singleton {
    INSTANCE;   
}

Initialization on Demand Holder.

Thread safe and lazy, but only for static fields.

public class Singleton {
    private Singleton() {}
  
    private static class SingletonHolder {
        private final static Singleton sInstance = new Singleton();
    }
  
    public static Singleton getInstance() {
        return SingletonHolder.sInstance;
    }
}

Double-Check Locking.

Thread safe and lazy.

Volatile is necessary, but can cause perfomance problems(?), and doesn't work on JDK4 and lower.

public class Singleton {
    private static volatile Singleton sInstance;

    private Singleton() {}

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

Object level lock vs Class level lock in Java

Stolen from HERE.

Object level lock is mechanism when we want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe.

public class DemoClass
{
    public synchronized void demoMethod() { ... }
}
public class DemoClass
{
    public void demoMethod() {
        synchronized (this) {
            // Thread safe code.
        }
    }
}
public class DemoClass
{
    private final Object lock = new Object();
    
    public void demoMethod() {
        synchronized (lock) {
            //Thread safe code.
        }
    }
}

Class level lock prevents multiple threads to enter in synchronized block in any of all available instances of the class on runtime. This means if in runtime there are 100 instances of DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads.

Class level locking should always be done to make static data thread safe. As we know that static keyword associate data of methods to class level, so use locking at static fields or methods to make it on class level.

public class DemoClass
{
    // Method is static.
    public synchronized static void demoMethod(){ ... }
}
public class DemoClass
{
    public void demoMethod()
    {
        synchronized (DemoClass.class) {
            // Thread safe code.
        }
    }
}
public class DemoClass
{
    // Static object.
    private final static Object lock = new Object();
 
    public void demoMethod() {
        synchronized (lock) {
            // Thread safe code.
        }
    }
}

Kotlin Example

class Singleton private constructor() {

    companion object {

        @Volatile private var instance: Singleton? = null

        fun getInstance() =
            instance ?: synchronized(this) {
                instance ?: Singleton().also { instance = it }
            }
    }
}
@prilaga
Copy link

prilaga commented Sep 19, 2021

This is the best thread safe singleton pattern

`
// ie:
// class Network(appliContext: Application) {
// companion object : SingletonHolder<Network, Application>(::Network){

open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@volatile private var instance: T? = null

fun getInstance(arg: A): T {
    val i = instance
    if (i != null) {
        return i
    }

    return synchronized(this) {
        val i2 = instance
        if (i2 != null) {
            i2
        } else {
            val created = creator!!(arg)
            instance = created
            creator = null
            created
        }
    }
}

}`

This is already implemented in kotlin, just use "by lazy". Open the "by lazy - SynchronizedLazyImpl" and you can find the same code as you provided.
But your approach is useful if we need to reset the instance.

@YoloSwagBot
Copy link

This is good to know, thank you for the information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment