我有一个处理HTTP请求的类。此类没有理由被多个线程使用,因此我想使其完全同步。
我之所以不简单地让此类不同步,是因为它包含多种此类用法:
if (jsonOutput != null) {
// ...
jsonOutput!!.writeTo(PrintWriter(writer))
// ...
}
请注意,我在空检查中使用了!!
运算符,在Kotlin中不需要。编译器强迫我添加它,因为“ jsonOutput是一个可变的属性,这次可能已经更改了”。
据我了解,这意味着编译器担心其他线程可能会修改此类属性的值;但是,在这种情况下,此类的给定对象永远不会被多个线程使用,因此对运算符的此调用是毫无意义的,并且会使代码混乱。
如何仅通过一个线程使该类的对象可用?
我曾考虑过将@Synchronized添加到每个方法中,但是1.听起来很麻烦,与Kotlin不同,并且2.我不知道编译器是否会考虑到足够的证据,以证明它不能被修改。
答案 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检查(或者只是块很大),这将很有帮助。