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 性能最高 线程不安全
相关推荐
Kapaseker1 天前
Compose 响应式布局的最后一块拼图—Grid
android·kotlin
我命由我123451 天前
Android buildSrc 模块问题:Gradle 的类 DefaultProject 被错误地尝试转换成 Apache Ant 的 Project 类
android·java·java-ee·kotlin·android jetpack·android-studio·android runtime
雨白1 天前
深入理解 Kotlin 协程 (四):大道至简,于微末的挂起恢复中衍化万物
kotlin
jinanwuhuaguo2 天前
OpenClaw 2026年4月升级大系深度解读剖析:从“架构重塑”到“信任内建”的范式跃迁
android·开发语言·人工智能·架构·kotlin·openclaw
我命由我123452 天前
Android Jetpack Compose - SearchBar(搜索栏)、Tab(标签页)、时间选择器、TooltipBox(工具提示)
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
Lsk_Smion2 天前
Hot100(开刷) 之 长度最小的数组--删除倒数第N个链表--层序遍历
java·数据结构·算法·kotlin
我命由我123452 天前
Android Jetpack Compose - 组件分类:布局组件、交互组件、文本组件
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
Kapaseker2 天前
让你的 App 成为 AI 的一环
android·kotlin
千码君20163 天前
kotlin:Jetpack Compose 给APP添加声音(点击音效/背景音乐)
android·开发语言·kotlin·音效·jetpack compose
Kapaseker3 天前
lazy 与 lateinit 到底有什么区别?
android·kotlin