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 性能最高 线程不安全
相关推荐
Kapaseker4 小时前
MVVM 旧城改造,边界划分各有招
android·kotlin
装杯让你飞起来啊21 小时前
第 2 周 Day 5-6:综合小游戏 —— 学生成绩管理系统
windows·microsoft·kotlin
装杯让你飞起来啊1 天前
Kotlin List / Array 与 for 循环
开发语言·kotlin·list
装杯让你飞起来啊1 天前
混合练习 —— 猜数字游戏
windows·游戏·kotlin
装杯让你飞起来啊1 天前
Kotlin 条件判断 if / when 与智能转换 smart cast
开发语言·python·kotlin
pengyu1 天前
【Kotlin 协程修仙录 · 金丹境 · 初阶】 | 并发艺术:async/await 与并发组合的优雅之道
android·kotlin
黄林晴1 天前
重磅发布!KMP 双端订阅支付彻底封神,一套代码搞定 iOS+Android
android·kotlin
alexhilton2 天前
揭密:Compose应用如何做到启动提升34%
android·kotlin·android jetpack
jason.zeng@15022073 天前
Androidr入门环境搭建
java·kotlin
jinanwuhuaguo4 天前
(第二十七篇)OpenClaw四月的演化风暴:OpenClaw 2026年4月全版本更新的文明级解读
大数据·人工智能·架构·kotlin·openclaw