在Kotlin获得单身人士

Ala*_*lan 9 kotlin

我一直在查看一些Google示例代码,他们似乎使用以下代码创建单例:

companion object {

        // For Singleton instantiation
        @Volatile
        private var instance: CarRepository? = null

        fun getInstance(carDao: CarDao) =
                instance ?: synchronized(this) {
                    instance ?: CarRepository(carDao).also { instance = it }
                }
    }
Run Code Online (Sandbox Code Playgroud)

所以我知道这@Volatile意味着

将带注释的属性的JVM支持字段标记为volatile,这意味着对此字段的写入会立即对其他线程可见.

是否所有单身实例都应标记为@Volatile?如果是这样,为什么?

最后,我不明白这个getInstance功能

instance ?: synchronized(this) {
    instance ?: CarRepository(carDao).also { instance = it }
}
Run Code Online (Sandbox Code Playgroud)

这到底是做什么的?

更新:来源:谷歌的向日葵 我改变了我自己使用的Repository和Dao名称,但它在Repository文件中是相同的逻辑.

kco*_*ock 5

有一个伟大的答案在这里为什么领域应该是震荡。本质上,没有它,一个线程可能会在实例完全构建之前获得对该实例的引用。

对于该getInstance()功能,您具有:

instance ?:
Run Code Online (Sandbox Code Playgroud)

这意味着如果该方法instance不为null,则将返回,否则将执行的右侧?:

synchronized(this) {
    instance ?:
}
Run Code Online (Sandbox Code Playgroud)

同样在这里,在第一次检查实例是否为null之后,在类(companion object)上同步之后,它再次检查非null值,并在执行最后一个命令之前将其返回(如果可用):

CarRepository(carDao).also { instance = it }
Run Code Online (Sandbox Code Playgroud)

这将初始化一个新变量CarRepository,然后使用该.also块,在返回之前将itCarRepository)分配给该instance字段。仅仅因为整个语句是一个表达式,这有点令人困惑。如果使它更加详细,则可能看起来像:

fun getInstance(carDao: CarDao): CarRepository {
    var cachedInstance = instance
    if (cachedInstance != null) {
        return cachedInstance
    }

    synchronized(this) {
        cachedInstance = instance
        if (cachedInstance == null) {
            cachedInstance = CarRepository(carDao)
            instance = cachedInstance
        }
        return cachedInstance
    }
}
Run Code Online (Sandbox Code Playgroud)

值得一提的是,我并不真的相信这个特定的例子是一个很好的模式。例如,考虑以下内容:

val carDao1 = CarDaoImpl1()
val carDao2 = CarDaoImpl2()

val carRepo1 = CarRepository.getInstance(carDao1)
val carRepo2 = CarRepository.getInstance(carDao2)

// carRepo2 actually points to carDao1!
Run Code Online (Sandbox Code Playgroud)