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 性能最高 线程不安全
相关推荐
YB13757 小时前
Kotlin 三类关键字
kotlin
撩得Android一次心动15 小时前
Jetpack Compose 知识点整理1【个人用】
android·学习·kotlin·android jetpack·compose
ForteScarlet16 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
JMchen12316 小时前
Cursor高阶玩法:.cursorrules编写与Spec-Driven开发实战,把AI调教成专属结对编程搭档
人工智能·vscode·kotlin·cursor·结对编程·spec-driven·.cursorrules
hai_android21 小时前
Kotlin 协程作用域源码剖析
android·kotlin
leluckys1 天前
【KMP】-KMP 项目commonMain、androidMain、iosMain 到底放什么?
kotlin
JMchen1231 天前
2026年六款主流AI编程工具深度实测:Cursor、Copilot、Claude Code等对比与选型思考
android·kotlin·copilot·ai编程·开发工具·cursor·claude code
hai_android1 天前
Kotlin 协程上下文:从 plus 到 CombinedContext,彻底搞懂左偏结构
android·kotlin
Android打工仔2 天前
Kotlin 协程源码解析(七)`delay()` 到底是如何在 `Dispatchers.Main` 上恢复的?
android·kotlin
Kapaseker2 天前
适配小米“中”折屏,非得买一台吗
android·kotlin