文章目录
- [Kotlin by lazy()总结](#Kotlin by lazy()总结)
Kotlin by lazy()总结
概述
by lazy() 是 Kotlin 中一种懒加载委托属性的实现方式,它允许我们定义一个属性,该属性在第一次被访问时才会被初始化,之后的访问会直接返回已初始化的值。
基本用法
kotlin
val myLazy by lazy{
println("计算")
"hello"
}
fun main() {
println(myLazy)
println(myLazy)
}
- 第一次访问,输出 "计算" 和 "hello"
- 第二次范围,只输出 "hello"
源码分析
Lazy 接口
kotlin
public interface Lazy<out T> {
// 懒加载的值
public val value: T
// 检查值是否被初始化
public fun isInitialized(): Boolean
}
lazy() 函数
kotlin
// 使用SynchronizedLazyImpl,线程安全
public actual fun <T> lazy(initializer: () -> T): Lazy<T> =
SynchronizedLazyImpl(initializer)
// 可以指定加载模式
public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
when (mode) {
// 完全线程安全模式
LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
// 线程安全模式,使用CAS
LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
// 线程不安全
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
}
// 可以指定锁对象
public actual fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> =
SynchronizedLazyImpl(initializer, lock)
SynchronizedLazyImpl 类
kotlin
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 // valatile 确保多线程的可见性
private val lock = lock ?: this // 锁对象
override val value: T
get() {
val _v1 = _value
// 如果有值则直接返回值
if (_v1 !== UNINITIALIZED_VALUE) {
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)
}
- 完全线程安全,存在锁竞争,一定程度上会影响性能。
- 先检查是否有值,如果有值则直接返回值。
- 如果没有值,进入同步代码块,再次检查是否有值,如果没有值则初始化值,完成初始化后,将initializer设置为null。
SafePublicationLazyImpl 类
kotlin
private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>, Serializable {
@Volatile private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
private val final: Any = UNINITIALIZED_VALUE
override val value: T
get() {
val value = _value
if (value !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return value as T
}
val initializerValue = initializer
if (initializerValue != null) {
val newValue = initializerValue()
// CAS:相等并交换返回true,不相等返回false
if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) {
initializer = null
return newValue
}
}
return _value as T
}
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)
companion object {
private val valueUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(
SafePublicationLazyImpl::class.java,
Any::class.java,
"_value"
)
}
}
- 无锁实现,高并发下性能好,但是初始化函数可能被多次执行。
- 使用 AtomicReferenceFieldUpdater 进行原子操作。
- 允许多线程同时执行初始化函数,使用 compareAndSet 确保只有第一个返回值被使用。
- 避免了锁竞争,高并发性能更好。
UnsafeLazyImpl 类
kotlin
internal class UnsafeLazyImpl<out T>(initializer: () -> T) : Lazy<T>, Serializable {
private var initializer: (() -> T)? = initializer
private var _value: Any? = UNINITIALIZED_VALUE
override val value: T
get() {
if (_value === UNINITIALIZED_VALUE) {
_value = initializer!!()
initializer = null
}
return _value as T
}
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)
}
- 线程不安全模式,性能最好。
模式区别
| 模式 | 优点 | 缺点 |
|---|---|---|
| SYNCHRONIZED | 完全线程安全 | 存在锁竞争,可能影响性能 |
| PUBLICATION | CAS无锁,高并发性能更好 | 初始化函数可能被多次执行 |
| NONE | 性能最高 | 线程不安全 |