当前位置: 首页 > 后端技术 > Java

【Java访谈】为什么引入偏向锁和轻量级锁,并介绍升级过程

时间:2023-04-01 22:41:49 Java

嗨,我是工作7年的Mic粉丝,来找我。他说最近被各种锁弄糊涂了。比如共享锁、排它锁、偏向锁、轻量级锁、自旋锁、重量级锁、间隙锁、键锁、意向锁、读写锁、乐观锁、悲观锁、表锁、行锁。然后前两天去面试,被问到偏向锁和轻量级锁,没回答。好了,关于Synchronized锁升级的原理,看看普通人和高手的解答。普通人:我觉得引入这些锁的目的应该是考虑性能问题。因为我记得如果给Synchronized加上重量级锁,它的线程会被阻塞,会影响性能。这就是引入偏向锁机制的原因。那么升级就是我们在获取锁的时候,通过偏向锁、轻量级锁、重量级锁的方式去竞争锁。师父:好的,面试官。在jdk1.6版本之前,Synchronized通过重量级锁来实现线程间的锁竞争。之所以称为重量级锁,是因为它的底层依赖于操作系统的互斥锁来实现互斥。Mutex是一种系统方法。由于权限隔离,当应用程序调用系统方法时,需要切换到内核态执行。这涉及到从用户模式切换到内核模式,这会导致性能损失。在jdk1.6版本中,synchronized增加了锁升级机制来平衡数据安全和性能。简单来说,当一个线程访问synchronized同步代码块时,synchronized会根据线程竞争情况,先尝试保证线程安全,而不加重量级锁。因此引入了偏向锁和轻量级锁的机制。偏向锁就是直接将当前锁偏向某个线程。简单的说就是通过CAS修改偏向锁标记。这种锁适用于同一个线程多次申请同一个锁资源,没有其他线程竞争的场景。轻量级锁也可以称为自旋锁。基于自适应自旋机制,采用多次自旋重试来竞争锁。自旋锁的好处是避免了从用户态切换到内核态带来的性能开销。Synchronized引入锁升级机制后,如果有线程竞争锁:首先,synchronized会尝试使用偏向锁来竞争锁资源。如果能竞争到偏向锁,则说明锁成功,直接返回。如果竞争锁失败,说明当前锁已经偏向其他线程。需要将锁升级为轻量级锁。在轻量级锁状态下,竞争锁的线程根据自适应自旋次数尝试抢占锁资源。如果锁在轻量级锁状态下仍然没有竞争,只能升级为重量级锁。在重量级锁状态下,不竞争锁的线程会被阻塞,线程状态为Blocked。处于锁等待状态的线程需要等待获得锁的线程触发唤醒。总的来说,Synchronized锁升级的设计思路,在我看来本质上是性能和安全的平衡,即如何在不加锁的情况下保证线程安全。这种思维在编程领域比较普遍。比如Mysql中的MVCC就是使用版本链来解决多个并行事务的竞争问题。以上是我对这个问题的理解。总结锁在程序中很常见。我们几乎每天都和锁打交道,比如Mysql中的行锁、表锁。所以它的重要性不言而喻。从大师的回答中,我们可以明显看出大师对Synchronized的理解是非常高的。喜欢我作品的朋友记得点赞收藏关注。版权声明:除特别声明外,本博客所有文章均采用CCBY-NC-SA4.0许可协议。转载请注明来自Mic带你学建筑!如果本文对您有帮助,请给个关注和点赞。您的坚持是我不断创作的动力。欢迎关注同名微信公众号获取更多技术干货!