轻量级锁到底是怎么回事啊啊啊啊
微信公众号:IT一刻钟。大型现实非严肃主义现场,一刻钟与你分享优质技术架构与见闻,做一个有剧情的程序员。关注可第一时间了解更多精彩内容,定期有福利相送哟。
之前我们讲了synchronized的原理,以及其中的偏向锁,送佛送到西,这次我们来说一说轻量级锁吧。
友情提醒:上面两篇没有看过的看官,请先阅读上面两篇之后,再读此篇,这样效果会更佳哦~
开局一张图。
看一张大图
流程讲解
当JVM关闭了偏向锁模式,对象在创建的时候,Mark Word中存储的是hash值,年代,是否偏向锁标志位为0,标志位是01。即一个无锁不可偏向状态。
轻量级锁逻辑:
1.当线程访问同步块,先判断锁状态标志位,如果是00,则说明是轻量级锁,JVM会先在当前线程栈帧中分配Lock Record空间;
2.将锁对象头中的Mark Word拷贝到当前线程的Lock Record中,称为Displaced Mark Word,然后使用CAS,将对象头中的Mark Word修改为指向当前线程栈中Lock Record的指针(如图)。如果成功,则获取轻量级锁,执行同步块中的代码,如果失败,则进行自旋竞争锁,自旋达到一定的次数如果依旧没有获取到锁,则升级为重量级锁(因为自旋会消耗CPU,为了避免无用的自旋,一旦锁升级为重量级锁,就不会恢复到轻量级锁,自旋的线程会被挂起阻塞住);
CAS操作之前堆栈与对象的状态:
CAS操作之后堆栈与对象的状态:
3.执行完同步代码块代码,退出同步代码块,使用CAS开始轻量级锁解锁,解锁的条件需要满足以下两个:
1)对象头Mark Word中锁记录指针是否依旧指向当前线程Lock Record
2)拷贝在当前线程Lock Record的Mark Word信息是否与对象头中的Mark Word一致
4.如果满足,则成功释放锁;
5.如果不满足,则释放锁,唤醒被挂起阻塞的线程,开始重量级锁的竞争。
注:当超过自旋阈值,竞争的线程就会把锁对象Mark Word指向重量级锁,导致Mark Word中的值发生了变化,当原持有轻量级锁的线程执行完毕,尝试通过CAS释放锁时,因为Mark Word已经指向重锁,不再是指向当前线程Lock Record的指针,于是解锁失败,这时原持有轻量级锁的线程就会知道锁已经升级为重量级锁。
偏向锁升级为轻量级锁:
1.先在原持有偏向锁的线程栈帧中分配Lock Record;
2.将对象头Mark Word拷贝到原持有偏向锁的线程Lock Record中,然后使用CAS,将对象头中的Mark Word修改为指向当前线程栈中Lock Record的指针。将原持有偏向锁的线程升级为持有偏向锁的线程;
3.唤醒线程,从安全点继续执行,执行完毕解锁。
轻量级锁的重入计数
我们看个demo,在该demo中重复3次获得锁,
synchronized(obj){ synchronized(obj){ synchronized(obj){ } } }
假设锁的状态是轻量级锁,如图反应了Mark Word和线程栈中Lock Record的关系,右边线程栈中包含3个指向当前锁对象的Lock Record。其中栈中最高位的Lock Record为第一次获取锁时分配的,其中Displaced Mark word为锁对象加锁前的Mark Word,而之后的锁重入,则会在线程栈中分配一个Displaced Mark word为null的Lock Record,用来重入计数。
每次释放锁的时候则会删除对应的Lock Record。 这就是轻量级锁的实现逻辑,相对于偏向锁来说,逻辑会稍微简单一些。
如果觉得学习到了,欢迎转发加关注,那是我分享的动力呀~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Azkaban、Xxl-Job与Airflow对比分析
概述 Xxl-Job 简述 XXL-JOB是一个国内轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。基于Java技术栈,调度中心与执行器通信基于作者另一个开源项目xxl-rpc,采用自建注册中心,整体架构简单明了,易于上手。 图片来源:http://www.xuxueli.com/xxl-job/#/?id=_533-架构图 项目地址 Github:xuxueli/xxl-job Azkaban 简述 Azkaban为LinkedIn开源的分布式工作流调度框架,项目起源于解决Hadoop Jop依赖管理问题,但实际已经是一个通用的工作流调度框架,适用于不同业务场景。 图片来源:https://github.com/azkaban/azkaban/blob/master/docs/figures/azkaban2overviewdesign.png 项目地址 Github:azkaban/azkaban Airflow 简述 Apache-Airflow 是Airbnb开源的一款数据流程工具,已经在Apache孵化成功,成为Apache的顶级项目。以非常灵活...
- 下一篇
ORACLE数据库启停概述
只要使用过oracle database,那么肯定执行过很多次的startup和shutdown的操作,但是你是否关心过这个过程发生了什么?这篇文章主要讲讲oracle启动与停止过程oracle后台发生的事情。 实例与数据库 首先需要弄清楚一些概念性的东西。我们平时只会说数据库是否启动,关闭很少用到实例的概念,说到实例,或许你想到的只是SID这个词。 实例和数据库是两个独立却又相互关联的两个不同的东西,他们都可以独立于彼此而存在。实例存在于内存,包含一大堆后台进程,而数据库存在于磁盘中。数据库和实例的关系可以是one to one或者one to many(例如RAC就是one to many的),但是绝对不存在一个实例对应多个数据库的情况。 实例启动的时候,会为其分配一个叫System Global Area(SGA)的系统全局区的内存区域以及一系列的后台进程,它们的主要任务是: 维护对内部数据的并发访问 缓存数据块 缓存未写入联机重做日志文件的重做数据 存储SQL的执行计划 下图展示了oracle实例的主要组件(图片来自oracle concept): 每个主机上可以创...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 2048小游戏-低调大师作品