Kotlin by lazy 實(shí)現(xiàn)原理
本文的目錄如下:
by lazy 到底是什么東西,怎么實(shí)現(xiàn)創(chuàng)建一個(gè)線程安全的單例?
Kotlin contract是什么
內(nèi)容開(kāi)始:

by lazy 到底是什么東西,怎么實(shí)現(xiàn)創(chuàng)建一個(gè)線程安全的單例?
我們通??梢允褂胋y viewModels就可以創(chuàng)建一個(gè)ViewModel供我們使用,不過(guò)這次先不談by viewModels(),我們看看by lazy:
如果直接寫(xiě)by lazy {} 會(huì)默認(rèn)返回一個(gè)SynchronizedLazyImpl

SyncrhonizedLazyImpl實(shí)現(xiàn)了Lazy接口,同樣實(shí)現(xiàn)了這個(gè)接口的還有后續(xù)會(huì)談及的ViewModelLazy。value表示一個(gè)不可變屬性,在SynchronizedLazyImpl中的實(shí)現(xiàn)如下:
本質(zhì)上還是一個(gè)雙重校驗(yàn)鎖的實(shí)現(xiàn)。不過(guò)Kotlin中是沒(méi)有synchronized塊的,這里使用了一個(gè)函數(shù)實(shí)現(xiàn)了這個(gè)效果:
monitorEnter和monitorExit看不到具體的實(shí)現(xiàn),這里不知道用了什么黑科技,不過(guò)應(yīng)該和JVM的monitorEnter和monitorExit的效果類似。這里需要具體說(shuō)一下是contract。
Kotlin contract是什么
參考內(nèi)容:
// Kotlin中的契約:https://droidyue.com/blog/2019/08/25/kotlin-contract-between-developers-and-the-compiler/
Kotlin contract表示Kotlin編譯器和開(kāi)發(fā)者之間的一個(gè)協(xié)定,請(qǐng)看如下的代碼:
傳入的safeRun lambda編譯器不知道它的執(zhí)行次數(shù),這樣有可能會(huì)修改val變量AppVersion,無(wú)法確定safeRun執(zhí)行時(shí),getAppVersion是否執(zhí)行完畢。
所以我們需要加一個(gè)constract告訴編譯器一些額外的信息:
通過(guò)callsInPlace確定runFunction只會(huì)在safeRun執(zhí)行時(shí)執(zhí)行,同時(shí)設(shè)置EXACTLY_ONCE確定只會(huì)執(zhí)行一次。