Kotlin中synchronized用Any()变量作参数的作用及疑问
Kotlin中synchronized使用私有LOCK变量而非伴生对象this的原因
专用LOCK变量的核心作用
- 锁的作用域完全可控:
private val LOCK = Any()是伴生对象内部的私有变量,只有当前同步块的逻辑会使用它作为锁。这种设计把锁的使用严格限制在需要同步的代码范围内,不会被外部或其他无关逻辑干扰。 - 避免无意义的锁竞争:如果用伴生对象的
this当锁,其他地方(比如伴生对象里的其他同步方法、甚至外部代码)可能也会用这个对象加锁,导致你的单例初始化逻辑和这些无关逻辑互相阻塞,既影响性能又增加死锁风险。 - 遵循封装原则:同步锁属于内部实现细节,用私有LOCK可以把这个细节完全封装起来,外部代码无法访问或修改锁的使用方式,保证代码的安全性和可维护性。
为什么不能用伴生对象的this替代?
- 锁粒度太粗:伴生对象是全局可见的单例,用它当锁意味着所有依赖这个对象的同步逻辑都会共享同一个监视器(Monitor)。比如如果后续在伴生对象里新增另一个同步方法,两个同步块会互相阻塞,完全没必要。
- 存在外部干扰风险:外部代码可以通过
YourClass.Companion直接拿到伴生对象,然后在自己的逻辑中加synchronized(YourClass.Companion),这会直接阻塞你的单例初始化流程,引发不可控的问题。 - 从Java监视器的本质来看:Kotlin的
synchronized本质是复用Java的对象监视器机制——每个对象都对应一个监视器,同一时间只有一个线程能持有该监视器。用专用LOCK时,这个监视器只服务于你的目标同步块;而用伴生对象this时,这个监视器是共享的,任何能拿到该对象的代码都能操作它,同步逻辑的安全性无法保障。
示例代码解析
你给出的单例实现代码:
companion object{ ... private val LOCK = Any() operator fun invoke(context: Context) = instance ?: synchronized(LOCK){ // 单例初始化逻辑 instance ?: createInstance(context).also { instance = it } } }
这里用私有LOCK确保只有单例初始化的代码会竞争这个锁,其他任何代码都无法访问该LOCK,同步逻辑的独立性和安全性都得到了保障。
内容的提问来源于stack exchange,提问作者Theprogrammingnoob
相关产品推荐
相关产品推荐

