面试必问--synchronized实现原理及锁升级过程你懂吗
synchronized实现原理及锁升级过程
前言:
synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的
尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchronized已经变得原来越强大了,本文带大家了解的是synchronized实现原理及锁升级过程,希望可以帮助到大家。
1.用法
synchronized可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。
synchronized有三种应用方式:
作用于实例方法,当前实例加锁,进入同步代码前要获得当前实例的锁;
作用于静态方法,当前类加锁,进去同步代码前要获得当前类对象的锁;
作用于代码块,对括号里配置的对象加锁。
2.实现原理
2.1 Java对象头
synchronized用的锁存在Java对象头里,Java对象头里的Mark Word默认存储对象的HashCode、分代年龄和锁标记位。在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。32位JVM的Mark Word可能变化存储为以下5种数据:
锁一共有四种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态随着竞争情况逐渐升级。为了提高获得锁和释放锁的效率,锁可以升级但不能降级,意味着偏向锁升级为轻量级锁后不能降级为偏向锁。
1.偏向锁
当一个线程访问同步块并获取锁时,会在对象头和栈帧的锁记录里存储偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需测试Mark Word里线程ID是否为当前线程。如果测试成功,表示线程已经获得了锁。如果测试失败,则需要判断偏向锁的标识。如果标识被设置为0(表示当前是无锁状态),则使用CAS竞争锁;如果标识设置成1(表示当前是偏向锁状态),则尝试使用CAS将对象头的偏向锁指向当前线程,触发偏向锁的撤销。偏向锁只有在竞争出现才会释放锁。当其他线程尝试竞争偏向锁时,程序到达全局安全点后(没有正在执行的代码),它会查看Java对象头中记录的线程是否存活,如果没有存活,那么锁对象被重置为无锁状态,其它线程可以竞争将其设置为偏向锁;如果存活,那么立刻查找该线程的栈帧信息,如果还是需要继续持有这个锁对象,那么暂停当前线程,撤销偏向锁,升级为轻量级锁,如果线程1不再使用该锁对象,那么将锁对象状态设为无锁状态,重新偏向新的线程。
2.轻量级锁
线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的MarkWord复制到锁记录中,即Displaced Mark Word。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁。如果失败,表示其他线程在竞争锁,当前线程使用自旋来获取锁。当自旋次数达到一定次数时,锁就会升级为重量级锁。
轻量级锁解锁时,会使用CAS操作将Displaced Mark Word替换回到对象头,如果成功,表示没有竞争发生。如果失败,表示当前锁存在竞争,锁已经被升级为重量级锁,则会释放锁并唤醒等待的线程。
流程大致如下:
结束:
今天就分享到这里,有不对需要改进的地方还望大佬们指出
喜欢这篇文章的话记得给作者点个关注点个喜欢
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
LeetCode第9题:回文数
题目 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 示例1:输入: 121 输出: true 示例2:输入: -121 输出: false 解释: 从左向右读, 为 -121。 从右向左读, 为 121-。因此它不是一个回文数。 示例3:输入: 10 输出: false 解释: 从右向左读, 为 01。因此它不是一个回文数。 代码 class Solution(object): def isPalindrome(self, x): """ :type x: int :rtype: bool """ return str(x) == str(x)[::-1] 本文链接:时光不写博客-Palindrome Number
- 下一篇
Android侧滑原来可以这么优雅
前言 侧滑手势在Android App应用得非常广泛,常见的使用场景包括:滑动抽屉、侧滑删除、侧滑返回、下拉刷新以及侧滑封面等。由于这些使用场景实在是太通用了,各路大神们八仙过海各显神通,每种侧滑场景都开源出了很多非常实用的框架,让我们的业务开发便利了很多。 目前,我们需要为每种场景引入不同的侧滑框架,由于App中的侧滑场景很多,我们项目中也就需要引入多个侧滑框架,而每个框架的使用方式各有不同,需要单独学习,团队的学习成本较高。 那么问题来了,有没有一种框架能解决所有侧滑需求呢? 一个框架解决所有侧滑需求?你确定不是在开玩笑? 在刚开始学习面向对象编程概念的时候我们就知道一个道理:解决一个软件问题,首先要将它抽象出来。 针对侧滑这个手势,我们能不能将它的概念抽象一下,到底侧滑指的是什么呢? 狭义侧滑:从屏幕的某侧的边缘开始向着远离该边缘的方向滑
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装Docker,最新的服务器搭配容器使用
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境