Synchronized锁升级的原理 系统管理员 2023-09-26 23:27 83阅读 0赞 ### Synchronized锁升级的原理 ### * JDK 1.6版本之前 * JDK 1.6版本之后 * * 无锁 * 偏向锁 * * 主要适用情况 * 轻量级锁 * * 升级条件 * CAS机制 * * CAS机制的问题 * 重量级锁 * * 实现方法 * 设计思想 # JDK 1.6版本之前 # JDK1.6版本之前是没有锁升级模式的。 Synchronized在**JDK1.6版本之前**是通过**重量级锁的方式**来实现线程之间的一个锁的竞争的。之所以称它为重量级锁是因为它的底层依赖操作系统层面的**Mutex Lock**来去实现互斥锁的一个功能。 Mutex是系统方法,由于权限隔离的关系,应用程序调用系统方法的时候,**需要切换到内核状态来执行**。那这样就涉及到用户态向内核态的一个切换。这个切换会带来性能上的一个损耗。 ![在这里插入图片描述][8d0996e318f34fe985d96c4f00cc59ef.png] # JDK 1.6版本之后 # 所以在JDK1.6版本之后,Synchronized增加了锁的升级这样一个机制,来平衡数据安全性和性能的一个关系。 简单来说,就是线程去访问synchronized同步代码块的时候,synchronized根据线程的竞争情况先去**尝试在不加重量级锁的情况下,去保证线程安全性**。所以引入了**偏向锁**和**轻量级锁**这样一个机制。 ## 无锁 ## 就是没有锁的过程。 ## 偏向锁 ## 偏向锁就是直接把当前的锁偏向于某个线程,简单来说就是通过**CAS机制来修改偏向锁的一个标记**。这种锁适合在同一个线程多次去申请同一个锁资源的情况并且没有其他线程竞争的一个场景中。 ### 主要适用情况 ### 当有一个资源,有一些线程去申请。但是这个一些线程不是一些,它是只有一个线程去申请。并且这个线程已经申请到了这个锁,没有其他的线程跟它去争抢这个锁。 那么当它进行同步代码块的执行的时候,它就没有必要释放这个锁了。因为它释放锁的过程是需要从用户态转换到内核态。然后这个过程是需要消耗很多资源的。所以说是**没有必要释放**的。 为了提高性能,引入了偏向锁。于是当有一个线程去执行去占有争夺这个资源的时候,它就不是释放锁了,继续持有这个锁。 ## 轻量级锁 ## 轻量级锁**也可以称为自旋锁**,它是基于自适应自旋的机制,通过多次自旋去重试竞争锁。自旋锁的优点在于它可以**避免用户态到内核态切换带来的一个性能损耗**。 Synchronized引入了锁升级这个机制之后,如果有线程去竞争锁,那么synchronized会尝试使用偏向锁的方式去竞争锁资源。如果能竞争到偏向锁,那么表示加锁成功,直接返回即可。**如果竞争偏向锁失败,说明当前已经有其他线程占用的偏向锁**,那么就需要将锁**升级到轻量级锁**,在轻量级锁的状态下,竞争锁的线程会根据自适应自旋次数去尝试自旋占用锁资源。**如果在轻量级锁状态下还是没有竞争到锁的话**,那么只能**升级到重量级锁**。 ### 升级条件 ### 如果有两个线程去争夺这个资源的话,那么偏向锁就会升级到轻量级锁。 ### CAS机制 ### 它先去判断一下这个锁是否还能够抢占到,如果抢占不到的话,它就会进行**一段忙等待时间**,也是**自旋操作**。 自旋一段时间,还是没有办法获得这个锁的时候,就会升级到重量级锁了。 它是有三个值的,是包括**内存地址**、**旧的预期值**、**要修改的新值**。它是先判断一下**当前的这个数据是否和自己的预期是一样的**。如果是一样的,说明没有被改变过。然后它就把新的值写入进去。 原子类的底层也是用CAS来实现的。就是说原子类它只有增长和减少,它都是写好的。它都是已经封装好的,并不会让你自己去实现的。 #### CAS机制的问题 #### 会有ABA问题,先把这个数据变成A然后变成B再变成A。它这个中间是有个变成B的过程的,但是如果是用这个**CAS判断的话**,它判断是**有两个A**,它是无法发现这个问题的。 但是一般来讲的话,CAS都会用**版本号**或者是**时间戳**来实现。就可能**避免**这个问题了。 ## 重量级锁 ## 那么在重量级锁的状态下,没有竞争到锁的线程会被阻塞。那么这个时候线程的状态叫Blocked,也就是处于锁等待的一个状态。对于锁等待状态下的线程需要等待获得锁的线程释放锁之后触发唤醒。 ### 实现方法 ### 管程实现或者底层操作之类的,就完全阻塞了。 # 设计思想 # 总的来说,Synchronized锁的审核及的设计思想本质上是一种**性能和安全性的一个平衡**。也就是说如何在不加锁的情况下,去保证线程的一个安全性,这种思想在编程领域是比较常见的。比如说**MySQL里面的MVCC使用了版本链**的方式来解决多个并行事务的竞争问题。 **参考资料**:[【Java面试】用架构师思维带你理解,关于Synchronized锁升级的原理][Java_Synchronized] [8d0996e318f34fe985d96c4f00cc59ef.png]: https://img-blog.csdnimg.cn/8d0996e318f34fe985d96c4f00cc59ef.png [Java_Synchronized]: https://www.bilibili.com/video/BV1wt4y147dQ/?spm_id_from=333.337.search-card.all.click&vd_source=a1af903e57688df870625021f7f3a7eb
还没有评论,来说两句吧...