Kotlin by lazy()总结

文章目录

  • [Kotlin by lazy()总结](#Kotlin by lazy()总结)
    • 概述
    • 基本用法
    • 源码分析
      • [Lazy 接口](#Lazy 接口)
      • [lazy() 函数](#lazy() 函数)
      • [SynchronizedLazyImpl 类](#SynchronizedLazyImpl 类)
      • [SafePublicationLazyImpl 类](#SafePublicationLazyImpl 类)
      • [UnsafeLazyImpl 类](#UnsafeLazyImpl 类)
      • 模式区别

Kotlin by lazy()总结

概述

by lazy() 是 Kotlin 中一种懒加载委托属性的实现方式,它允许我们定义一个属性,该属性在第一次被访问时才会被初始化,之后的访问会直接返回已初始化的值。

基本用法

kotlin 复制代码
val myLazy by lazy{
    println("计算")
    "hello"
}

fun main() {
   println(myLazy)
   println(myLazy)
}
  1. 第一次访问,输出 "计算" 和 "hello"
  2. 第二次范围,只输出 "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)
}
  1. 完全线程安全,存在锁竞争,一定程度上会影响性能。
  2. 先检查是否有值,如果有值则直接返回值。
  3. 如果没有值,进入同步代码块,再次检查是否有值,如果没有值则初始化值,完成初始化后,将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"
        )
    }
}
  1. 无锁实现,高并发下性能好,但是初始化函数可能被多次执行。
  2. 使用 AtomicReferenceFieldUpdater 进行原子操作。
  3. 允许多线程同时执行初始化函数,使用 compareAndSet 确保只有第一个返回值被使用。
  4. 避免了锁竞争,高并发性能更好。

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 性能最高 线程不安全
相关推荐
我命由我123453 小时前
Android 在构建过程中,发现有两个依赖库都包含了相同路径的资源文件
android·java·开发语言·java-ee·kotlin·android-studio·android runtime
Coffeeee3 小时前
谷歌的一个优化建议,让我重新学了一遍Android里面如何正确处理位图
android·google·kotlin
Android打工仔2 天前
Continuation 到底是谁创建的?
android·kotlin
Android-Flutter2 天前
android fragment 使用
android·kotlin
alexhilton2 天前
响应式的Android身份验证架构
android·kotlin·android jetpack
zzq77972 天前
Android 16 API 36 升级后 APP 加固兼容性问题解析
android·开发语言·安全·kotlin·安卓·安全架构
Sirens.3 天前
从参考 iCost 到做自己的 OneLedger:一个 Android 本地记账 App 的开发记录
android·kotlin·room·jetpack compose·记账 app
Hrain-AI3 天前
2026 企业 AI 编程智能体实战:Codex 与 Claude Code
开发语言·人工智能·kotlin
btown6 天前
Kotlin 版 MyBatis-Plus 查询优雅解决方案
kotlin
小二·6 天前
车载数字座舱实战:用魔珐星云打造下一代智能驾乘助手(附 Android/Kotlin 完整代码)
开发语言·kotlin