val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

fun main() {
    println(lazyValue) // 첫 실행. 람다 실행 후 결과를 기억.
    println(lazyValue) // 후속호출(get()) 기억된 결과를 반환.
}

실행결과
computed!
Hello
Hello

lazy의 파라미터 - LazyThreadSafetyMode.PUBLICATION

public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
    when (mode) {
        LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
        LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
        LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
    }

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
val lazyValue: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
    println("computed!")
    "Hello"
}

fun main() = runBlocking<Unit> {
    GlobalScope.launch {
        println(lazyValue)
    }
    GlobalScope.launch {
        println(lazyValue)
    }
}

실행결과
computed!
Hello
computed!
Hello

lazy의 파라미터 - LazyThreadSafetyMode.NONE

abstract class BaseActivity<T : ViewDataBinding>(
    @LayoutRes private val layoutId: Int
    ) : AppCompatActivity() {
    protected val binding: T by lazy(LazyThreadSafetyMode.NONE) {
        DataBindingUtil.setContentView(this, layoutId)
    }

    init {
        addOnContextAvailableListener {
            binding.notifyChange()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.lifecycleOwner = this
    }

    override fun onDestroy() {
        binding.unbind()
        super.onDestroy()
    }

    protected inline fun bind(block: T.() -> Unit) {
        binding.apply(block)
    }
}