Java并发机制底层实现原理-synchronized
章节目录
- synchronized的实现原理与应用
synchronized 重量级锁
1.6版本之前 synchronized 被称之为 重量级锁
1.6版本对 synchronized 进行了优化,主要优化的点在于 减少 获得锁和释放锁带
来的性能消耗,为实现这个目的引入了偏向锁、与轻量级锁。
synchronized 实现同步的基础
Java中每一个对象都可以作为锁。
普通同步方法,锁是当前实例对象。
静态同步方法块,锁是当前类的Class对象。
对于同步方法块,锁是synchronized括号里配置的对象。
synchronized 同步锁的获取 底层原理
如下图所示:
synchronized锁的存储位置
synchronized 用的锁是存在java对象头里的。
对象头中的Mark-word 默认存储对象的hashcode、分代年龄、和锁标志位。
Mark-word 中存储的数据会随着锁标志位的变化而变化
轻量级锁-00
重量级锁-10
GC标记-11
偏向锁-01
锁的升级与对比
Java SE 1.6 当中锁一共有4种状态,级别从低到高一次为:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。锁可以升级但不能降级,这种锁升级但不能降级的策略,目的是为了提高获得锁与释放锁的效率。
1.偏向锁原理
偏向锁的优点及初始化过程:
- 加锁解锁不需要额外的资源消耗,只需要对比当前线程id在对象头中是否存储指向当前线程的偏向锁。如果存在,表示当前线程已经获得锁。如果测试失败,则查询当前mark word中的偏向锁标志是否设置成为1,如果没有设置,则使用CAS竞争锁(非偏向锁状态),如果设置了偏向锁标志,则尝试使用CAS将对象头的偏向锁指向当前线程。
偏向锁的撤销:
- 偏向锁使用了一种等到竞争出现才释放锁的机制,当其他线程尝试竞争偏向锁的时候,持有偏向锁的线程才会释放锁。偏向锁的撤销,需要等待全局安全点,这个时间点上没有正在执行的字节码。它首先会暂停拥有偏向锁的线程,然后检查持有偏向锁的线程活着,如果线程不处于活动状态,则将对象头设置为无锁状态。如果线程仍活着,拥有偏向锁的栈会被执行完。
2.轻量级锁原理
轻量级锁加锁:
- 线程在执行同步块之前,JVM会先在当前线程的栈桢中创建存储锁记录的空间,并将对象头中的mark word 复制到锁记录当中,然后线程尝试使用CAS将对象头中的 mark word 替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋锁来获取锁。
轻量级锁解锁
- 轻量级解锁时,会使用原子的CAS将锁记录(Displaced Mark Word)替换回到
对象头,如果成功,则表示没有发生竞争。如果失败,表示当前锁存在竞争,锁就会膨胀为重量级锁。
总结
锁 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁都不需要额外的消耗,和执行非同步的方法相比只存在纳秒级差距 | 如果线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块的场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了应用的相应速率 | 如果始终得不到竞争的线程,适用自旋会消耗cpu,造成cpu空转 | 追求响应时间,同步块执行速度非常快 |
重量级锁 | 线程竞争不使用自旋,不会消耗cpu | 线程阻塞,响应时间缓慢 | 追求吞吐量,同步块执行速度较长 |
不同锁的优缺点
锁 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁都不需要额外的消耗,和执行非同步的方法相比只存在纳秒级差距 | 如果线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块的场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了应用的相应速率 | 如果始终得不到竞争的线程,适用自旋会消耗cpu,造成cpu空转 | 追求响应时间,同步块执行速度非常快 |
重量级锁 | 线程竞争不使用自旋,不会消耗cpu | 线程阻塞,响应时间缓慢 | 追求吞吐量,同步块执行速度较长 |

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
还在找远控?来看我用十几行python代码写个简易远程控制
刚开始学习编程的同学可能经常会问:“我学了这个干什么用?买菜的时候掏出电脑来编个程序算算多少钱?” 其实,这跟大家的知识面和入门选择的语言有很大关系,大部分同学会选择C语言来入门编程,C语言虽然简洁,但是面向过程的编程方式总会让人觉得枯燥无味,无所适从。 那咱们现在做个有意思的,做个超级简易的远程控制软件,好吧~其实顶多算个脚本。 既然是远控,那就需要确定两个功能: 1、远程 即通过网络访问外部主机(包括内网),我们可以利用Python中封装好的 socket库,可以实现远程传输文本、文件、视频等。 Python socket详情介绍 2、控制 控制,最简单的理解就是执行命令,那么我们可以采用Python中的 os库,即可执行Linux shell 命令。 Python os详情介绍 下面就是代码,保存成.py文件,然后先执行server.py 再执行 client.py。 服务端,保存成 server.py #!/usr/bin/env python # -*- coding:utf-8 -*- import socket import os line=socket.socket(s...
-
下一篇
python基础知识
1、print()函数print函数用于向控制台、python解释器、cmd命令行输出你想要输出的内容。print函数有输入参数,可以是字符串、数字、变量等等,也可以是它们的混合,不同对象之间可以使用,来分隔,print函数遇到,的时候会输出一个空格来作为分隔输出的效果。注意:在print函数中,如果输入的内容是可以继续计算或者合并的,那么python会先计算或者合并之后再输出。如:print(100+200)print('a'+'b')会输出数字300以及字符串'ab'2、input()函数用于从命令行、python解释器获取用户的输入,从subline text中无法输入。用户的所有输入都会被当做是str类型,即字符串类型,用户可以将input的输入内容放入变量中,即:name=input()用于保存输入的内容用作后续代码的指代。同时,为了更友好的界面,可以给input函数输入参数值,参数值可以是一个字符串,也可以是一个变量的指代,用于在提示用户输入的时候给出详细的说明,即:name=input('inpurt your name:')或者i='please input here:...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker容器配置,解决镜像无法拉取问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- MySQL数据库在高并发下的优化方案