Kotlin并发性:将类标记为已同步

时间:2018-10-11 15:44:01

标签: multithreading kotlin

我有一个处理HTTP请求的类。此类没有理由被多个线程使用,因此我想使其完全同步。

我之所以不简单地让此类不同步,是因为它包含多种此类用法:

if (jsonOutput != null) {
    // ...

    jsonOutput!!.writeTo(PrintWriter(writer))

    // ...
}

请注意,我在空检查中使用了!!运算符,在Kotlin中不需要。编译器强迫我添加它,因为“ jsonOutput是一个可变的属性,这次可能已经更改了”。

据我了解,这意味着编译器担心其他线程可能会修改此类属性的值;但是,在这种情况下,此类的给定对象永远不会被多个线程使用,因此对运算符的此调用是毫无意义的,并且会使代码混乱。

如何仅通过一个线程使该类的对象可用?

我曾考虑过将@Synchronized添加到每个方法中,但是1.听起来很麻烦,与Kotlin不同,并且2.我不知道编译器是否会考虑到足够的证据,以证明它不能被修改。

1 个答案:

答案 0 :(得分:3)

  

据我了解,这意味着编译器担心其他线程可能会修改此类属性的值;但是,在这种情况下,此类的给定对象永远不会被多个线程使用,因此对运算符的此调用是毫无意义的,并且会使代码混乱。

不仅是其他线程,而且在第一// ...部分发生的任何方法调用都可能会将jsonOutput设置为null

无论如何,用@Synchronized注释确实无济于事,但出于同样的原因,也不会“将类标记为已同步”。

但是,解决问题的正确方法有所不同:

jsonOutput?.let { 
    // ...
    it.writeTo(PrintWriter(writer)) // it refers to jsonOutput value
    // ...
}

这一次获得jsonOutput的值,因此编译器知道它不在null内的let中。您还可以命名参数:

jsonOutput?.let { jsonOutput ->
    // ...
    jsonOutput.writeTo(PrintWriter(writer))
    // ...
}

如果您嵌套了null检查(或者只是块很大),这将很有帮助。