当前位置:网站首页>synchronized锁原理详解
synchronized锁原理详解
2022-08-02 03:27:00 【浮空over】
文章目录
前言(堆区对象组成部分)
在理解锁实现原理之前先了解一下Java的对象头和Monitor,在JVM中,对象是分成三部分存在的:
- 对象头
- 实例数据
- 对其填充
实例数据和对其填充与synchronized无关,对象头是我们需要关注的重点,它是synchronized实现锁的基础,因为synchronized申请锁、上锁、释放锁都与对象头有关。
一、synchronized的使用
1.synchronize(this)
锁定实例化的对象,每个对象有其独立的对象锁,互不干扰
2.synchronize(Object o)
synchronize(Object o),每一个object相当于一把锁,不同的锁有不同的钥匙,可以减少锁竞争
3.synchronize放在函数签名里
synchronize放在函数签名中和synchronize(this)使用的是同一对象锁,一个钥匙多把锁
二、锁的不同状态
JDK6之前只有两个状态:无锁、有锁(重量级锁),
而在JDK6之后对synchronized进行了优化,新增了两种状态,总共就是四个状态:
- 无锁状态
- 偏向锁
- 轻量级锁
- 重量级锁
其中无锁就是一种状态了。锁的类型和状态在对象头Mark Word中都有记录,在申请锁、锁升级等过程中JVM都需要读取对象的Mark Word数据。
每一个锁都对应一个monitor对象,在HotSpot虚拟机中它是由ObjectMonitor实现的(C++实现)。每个对象都存在着一个monitor与之关联,对象与其monitor之间的关系有存在多种实现方式,如monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个monitor被某个线程持有后,它便处于锁定状态。
三、synchronized 原理
Synchronized是关键字,内置语言实现
Synchronized底层使用指令码方式来控制锁的,映射成字节码指令就是增加来两个指令
monitorenter
monitorexit
当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取锁则阻塞;当遇到monitorexit指令时锁计数器-1,如果计数器为0则释放锁。
四、锁升级机制
上面讲到的对象头8个字节,32位
上面介绍的四种状态,并且会因实际情况进行升级,过程如下
1.无锁
对象头前25位存hashCode,4位存分代年龄,1位判断是否是偏向锁(0),2位锁标志位(01)
2.偏向锁(只偏向一个)
对象头23位线程ID,2位时间戳(超时会判断线程存不存在,若不存在,变为无锁状态),4位分代年龄,(1)(01),这次拿到锁之后,下次直接拥有锁
一句话总结它的作用:减少统一鲜橙获取锁的代价。在大多数情况下,锁不存在多线程竞争,总是由同一鲜橙多次获得,那么此时就是偏向锁。
过程: 先说无锁—>偏向锁。锁的标志位都为01。
当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要花费CAS操作来加锁和解锁,而只需简单的测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁,如果测试成功,表示线程已经获得了锁,如果测试失败,则需要再测试下Mark Word中偏向锁的标识是否设置成1(表示当前是偏向锁),如果没有设置,则使用CAS竞争锁,如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程。
要注意的是,偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着,如果线程不处于活动状态,则将对象头设置成无锁状态,如果线程仍然活着,拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,栈中的锁记录和对象头的Mark Word要么重新偏向于其他线程,要么恢复到无锁或者标记对象不适合作为偏向锁,最后唤醒暂停的线程。
3.轻量级锁(2个线程,竞争对手不多)
30位指向虚拟机栈执行代码的地址,(00)线程不会阻塞,一前一后去执行。自己去抢线程,如果始终得不到锁,自旋(50次)会消耗cpu
4.重量级锁(系统分配)
30位指向monitor地址,(10),系统分配由用户空间到了内核空间,一定会有一个人能分配到内存,竞争锁的线程会被阻塞。(多个线程排队—>objectMonitor—>wait()还想排队当notify()时再次排队,不想排队则结束)
五、Synchronized缺点
- 无法判断锁状态,不知当前线程是否锁住 还是没有锁住
- 不可中断,如果线程迟迟拿不到一把锁,这把锁被其他线程占用,会出现改线程一直等待
- Synchronized非公平锁,任何新线程过来 与原先排队等待的线程 都有同样的机会获得锁
- 关键字实现获取锁与释放锁,中间不可控
- 当锁产生竞争时,两个和三个线程争取一把锁,没有获得到,此时改为系统主动分配,这也
- 是重量级锁由来。此时会造成 用户空间切换到内核空间
六、Synchronized和Lock比较
- Synchronized是关键字,内置语言实现,Lock是接口。
- Synchronized在线程发生异常时会自动释放锁,因此不会发生异常死锁。Lock异常时不会自动释放锁,所以需要在finally中实现释放锁。
- Lock是可以中断锁,Synchronized是非中断锁,必须等待线程执行完成释放锁。
- Lock可以使用读锁提高多线程读效率。
边栏推荐
- 文件上传漏洞
- uniapp | Compilation error after updating with npm update
- php的curl函数模拟post数据提交,速度非常慢
- 浅谈性能优化:APP的启动流程分析与优化
- VIKINGS: 1 vulnhub walkthrough
- (2) Sequence structures, Boolean values of objects, selection structures, loop structures, lists, dictionaries, tuples, sets
- 备战金九银十:Android 高级架构师的学习路线及面试题分享
- C language uses stack to calculate infix expressions
- uniapp发布到微信小程序:分包、删减代码全过程
- 同时安装VirtualBox和VMware,虚拟机如何上网
猜你喜欢
一个网络安全小白鼠的学习之路——nmap的基本使用
CTF之xxe
树莓派4b安装win11/10过程全教程(附蓝屏inaccessible boot device解决办法)
mysql 原生语句点滴学习记录
file contains vulnerabilities
完整安装 Laravel-Admin 框架
如何在正则表达式里表达可能存在也可能不存在的内容?
uniapp发布到微信小程序:分包、删减代码全过程
张量乘积—实验作业
(2) Sequence structures, Boolean values of objects, selection structures, loop structures, lists, dictionaries, tuples, sets
随机推荐
file contains vulnerabilities
文件包含漏洞
关于我的专利、软著~
(3) string
View的滑动
敏感信息泄露
ES6 iterator explanation example
加密数字货币前传:从大卫·乔姆到中本聪
Eric target penetration test complete tutorial
【一句话攻略】彻底理解JS中的回调(Callback)函数
2022年中高级 Android 大厂面试秘籍,为你保驾护航金九银十,直通大厂
面试知识点整理:Skia 架构的场景渲染
By figure, a (complete code at the end)
A code audit notes (CVE - 2018-12613 phpmyadmin file contains loopholes)
hackmyvm: may walkthrough
hackmyvm-hopper预排
PHP hash加密与解密
The first time to tear the code by hand, how to solve the problem of full arrangement
树莓派4b安装win11/10过程全教程(附蓝屏inaccessible boot device解决办法)
OPENSSL基本实验以及OPENSSL详解