Kotlin的?.let
是否线程安全?
假设一个变量a
可以在不同的线程中更改。使用a?.let { /* */ }
是否线程安全?如果它等价于if (a != null) { block() }
,那么在if
中它不为null,在block
中它会变成null的情况是否可能发生?
Kotlin的?.let
是否线程安全?
假设一个变量a
可以在不同的线程中更改。使用a?.let { /* */ }
是否线程安全?如果它等价于if (a != null) { block() }
,那么在if
中它不为null,在block
中它会变成null的情况是否可能发生?
a?.let { block() }
的确等价于 if (a != null) block()
。
这也意味着,如果a
是一个可变变量,则:
如果a
是可变变量,那么在空值检查之后,它可能会被重新分配,并在block()
执行期间保持为null
值;
所有与并发相关的影响都有权利,如果a
在线程之间共享,则需要适当的同步来避免竞态条件,如果block()
再次访问a
;
然而,由于let { ... }
实际上将其接收者作为单个参数传递给它所采取的函数,因此它可以用于捕获a
的值并在lambda中使用它,而不是在block()
中再次访问该属性。例如:
a?.let { notNullA -> block(notNullA) }
// with implicit parameter `it`, this is equivalent to:
a?.let { block(it) }
在这里,作为参数传递到lambda的a
的值保证与检查null时的值相同。但是,在block()
中再次观察a
可能会返回null或不同的值,并且观察给定实例的可变状态也应该被正确同步。
let
参数始终与?.
检查到的值相同,因此永远不会为null。但是,如果a
在此期间发生了更改,则不会反映出来。) - gidds?.
运算符的工作方式:它从其左侧的表达式中获取值(这可能意味着调用 getter 或其他内容),检查它是否为空,如果不为空,则调用该值后面的方法。在这种情况下,let()
然后将该值作为参数传递给函数。因此,在任何时候都没有机会获取不同的值。当然,如果该值是可变对象,则其状态可以更改。但它必须是相同的对象。 - giddsblock
是无参的,所以我会说它成立,但并不能完全解释 ?.let { ... }
的语义。感谢您的提醒! - hotkeya != null
检查是原子和同步的吗?”看起来好像不是。 - 4ntoine
a
可能为 null,但参数it
不可能为空。也就是说,这段代码等价于val copy = a; if (copy != null) { block(copy) }
。 - JB Nizetif (a != null) { a.someFunction() }
时一样)。 - marstrana
是Int?
类型):智能转换为 'Int' 是不可能的,因为 'a' 是一个可变属性,在此期间可能已经被更改
。 - marstran