val属性是否线程安全?Code A中val属性线程安全性存疑
为什么Kotlin中这个val属性看似线程不安全?
你抓得很准!这段代码里的val a确实不具备线程安全性,表现得跟普通var变量一样——不同线程完全可能读到a的不同值,这背后的原因其实是你对val的线程安全特性理解有个小误区:
Kotlin的val关键字只保证变量本身不能被重新赋值,但如果val是一个计算属性(也就是自定义了getter逻辑),它的线程安全性完全由getter依赖的状态决定。
看你给出的代码:
var aImpl = 0 val a: Int get() = aImpl fun seta(){ aImpl=5 }
这里的val a每次被读取时,都会直接返回aImpl的当前值,而aImpl是一个普通的var变量,没有任何线程同步措施:
- 当多个线程同时调用
seta()修改aImpl,或者同时读取a的时候,会出现可见性问题——一个线程修改的aImpl值可能无法及时被其他线程感知到,甚至出现指令重排导致的读取不一致。 - 本质上,
val a只是一个“门面”,真正的状态存在aImpl里,而aImpl的线程不安全直接传导给了a。
如果想要让a具备线程安全的读取特性,可以试试这两种方案:
- 给
aImpl添加@Volatile注解,保证多线程下的可见性:
@Volatile var aImpl = 0 val a: Int get() = aImpl fun seta(){ aImpl=5 }
- 使用
synchronized同步读写操作,同时保证可见性和原子性:
private var aImpl = 0 val a: Int get() = synchronized(this) { aImpl } fun seta(){ synchronized(this) { aImpl=5 } }
内容的提问来源于stack exchange,提问作者HelloCW
相关产品推荐
相关产品推荐

