设计模式—单例

只介绍懒汉模式,并且线程安全的写法

Java版本

1、双重检查,加锁

public class Singleton {
    // --- 双层锁定 线程安全
    private static volatile Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

分析:当同时有两个线程访问getInstance()时,synchronized 前的instance == null两个线程都会通过,当执行synchronized (Singleton.class)时候会有一个线程进入,另一个线程等待的情况,进入的线程会再次对instance == null进行判断并创建一个Singleton的实例,然后结束synchronized 代码块。另一个等待线程进入synchronized 代码块,在进行instance == null判断时会发现instance 已经不再为null,从而不再创建Singleton的实例,这样就可以确保Singleton对象在多线程情况下也只有一个实例。那你会不会问在synchronized 前的instance == null又有什么作用呢?这个主要是考虑效率的问题,如果不在synchronized 前加上instance == null,就会发现每次调用都会对线程加锁,消耗资源又达不到高效性。

2、静态内部类,写法简单优雅

public class Singleton {
    // --- 静态内部类 线程安全
    private Singleton() {}

    public static Singleton getInstance() {
        return Holder.instance;
    }

    private static class Holder {
        private static Singleton instance = new Singleton();
    }

}

分析:其实这是一种偷懒的线程安全实现方法,为什么说是偷懒那?那是因为这种实现利用了类的加载是线程安全的原理。当这个Singleton 被加载的时候,其中的内部类Holder 并不会被加载,只有当调用getInstance()中的Holder.instance时Holder 才会被加载,而类的加载一定是线程安全,至于为什么类的加载是线程安全的请 自行百度

Kotlin版本

1、双重检查,加锁

class Singleton private constructor() : IImageLoader {
    companion object {
        @Volatile
        private var INSTANCE: Singleton ? = null

        fun instance(): Singleton {
            INSTANCE ?: synchronized(Singleton @ this) {
                if (INSTANCE == null)
                    INSTANCE = Singleton (loader)
            }
            return INSTANCE!!
        }
    }
}

或者

class SingletonK private constructor() {
    companion object {
        val Instanc: SingletonK by lazy { SingletonK() }
    }
}

分析:为什么val Instanc: SingletonK by lazy { SingletonK() }这样就可以实现线程安全?这要看lazy的实现源码lazy其实是可以有参数的,它的参数类型是LazyThreadSafetyMode,当我们不传的时候默认是LazyThreadSafetyMode.SYNCHRONIZED也就是线程安全,那么我们再看看这种情况下的具体实现!

@kotlin.jvm.JvmVersion
public fun  lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy =
        when (mode) {
            LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
            LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
            LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
        }
private class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = null) : Lazy, Serializable {
    private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE
    // final field is required to enable safe publication of constructed instance
    private val lock = lock ?: this

    override val value: T
        get() {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }

            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                }
                else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null
                    typedValue
                }
            }
        }

    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE

    override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."

    private fun writeReplace(): Any = InitializedLazyImpl(value)
}

当我们看到get中的下面代码

    val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
        @Suppress("UNCHECKED_CAST")
        return _v1 as T
    }

    return synchronized(lock) {
        val _v2 = _value
        if (_v2 !== UNINITIALIZED_VALUE) {
            @Suppress("UNCHECKED_CAST") (_v2 as T)
        }
        else {
            val typedValue = initializer!!()
            _value = typedValue
            initializer = null
            typedValue
        }
    }

这就不用我多说了,底层实现还是一个双重检查加锁的实现!!!

你可能感兴趣的:(设计模式—单例)