只介紹懶漢模式,并且線程安全的寫法
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;
}
}
分析:當(dāng)同時有兩個線程訪問getInstance()
時深浮,synchronized 前的instance == null
兩個線程都會通過,當(dāng)執(zhí)行synchronized (Singleton.class)
時候會有一個線程進(jìn)入菌瘫,另一個線程等待的情況布卡,進(jìn)入的線程會再次對instance == null
進(jìn)行判斷并創(chuàng)建一個Singleton的實例,然后結(jié)束synchronized 代碼塊栖忠。另一個等待線程進(jìn)入synchronized 代碼塊贸街,在進(jìn)行instance == null
判斷時會發(fā)現(xiàn)instance 已經(jīng)不再為null,從而不再創(chuàng)建Singleton的實例捐川,這樣就可以確保Singleton對象在多線程情況下也只有一個實例逸尖。那你會不會問在synchronized 前的instance == null
又有什么作用呢?這個主要是考慮效率的問題冷溶,如果不在synchronized 前加上instance == null
逞频,就會發(fā)現(xiàn)每次調(diào)用都會對線程加鎖,消耗資源又達(dá)不到高效性苗胀。
2瓦堵、靜態(tài)內(nèi)部類菇用,寫法簡單優(yōu)雅
public class Singleton {
// --- 靜態(tài)內(nèi)部類 線程安全
private Singleton() {}
public static Singleton getInstance() {
return Holder.instance;
}
private static class Holder {
private static Singleton instance = new Singleton();
}
}
分析:其實這是一種偷懶的線程安全實現(xiàn)方法陷揪,為什么說是偷懶那?那是因為這種實現(xiàn)利用了類的加載是線程安全的原理卦绣。當(dāng)這個Singleton 被加載的時候飞蚓,其中的內(nèi)部類Holder 并不會被加載,只有當(dāng)調(diào)用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() }
這樣就可以實現(xiàn)線程安全叔壤?這要看lazy的實現(xiàn)源碼lazy其實是可以有參數(shù)的口叙,它的參數(shù)類型是LazyThreadSafetyMode
,當(dāng)我們不傳的時候默認(rèn)是LazyThreadSafetyMode.SYNCHRONIZED
也就是線程安全,那么我們再看看這種情況下的具體實現(xiàn)俺亮!
@kotlin.jvm.JvmVersion
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
when (mode) {
LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
}
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, 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)
}
當(dāng)我們看到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
}
}
這就不用我多說了,底層實現(xiàn)還是一個雙重檢查加鎖的實現(xiàn)F艟摺!拷沸!