访问synchronized属性后两线程能否同时调用同一方法?Kotlin线程安全疑问
问题解答
原实现存在的问题
原代码的并发场景下确实存在缺陷:
asStopped读取state和后续调用start()修改state是两个独立的非原子操作:两个线程同时执行player.asStopped?.start()时,会同时读取到当前state为Stopped实例,都能拿到非空的Stopped对象引用,继而都会触发start()方法。- 原始
start()方法没有同步控制,也没有状态二次校验:即便state属性本身的读写通过synchronized委托保证了原子性,两个线程仍会先后执行state = Started(...)赋值操作,会导致Started实例被重复创建,如果Started构造逻辑存在副作用,还会触发多次不符合预期的执行逻辑。
调整后的实现合理性
你给出的调整方案是完全可行的,刚好解决了上述并发问题:
- 给
start()方法加@Synchronized注解,保证同一时间只有一个线程能进入当前Stopped实例的start()方法执行修改逻辑,避免并行修改冲突。 - 方法开头增加
if(state is Started) return的二次校验:第一个进入方法的线程会将state修改为Started,后续拿到锁进入方法的线程读到最新的state值后会直接返回,不会重复执行赋值逻辑。
额外注意事项
需要确认你使用的by synchronized属性委托确实保证了state的读写操作具备原子性和内存可见性,避免synchronized方法内读取state时读到旧的CPU缓存值即可。如果后续状态切换逻辑更复杂,也可以考虑将状态修改的原子性校验封装在属性的自定义委托逻辑中,当前调整方案已经足够应对你描述的场景。
内容的提问来源于stack exchange,提问作者Renetik
相关产品推荐
相关产品推荐

