synchronized中锁是怎么升级的
在JDK1.6以前,使用synchronized就只有一种方式即重量级锁,而在JDK1.6以后,引入了偏向锁,轻量级锁,重量级锁,来减少竞争带来的上下文切换。
锁升级主要依赖对象头中的Mark Word中的锁标志位和释放偏向锁标识位。
一般的synchronized同步锁升级步骤是:偏向锁 -> 轻量级锁 -> 重量级锁。
注意:锁只能升级,不能降级。
偏向锁
偏向锁,顾名思义是偏向某一个线程的锁,在该某个线程第一次成功锁时,会在对象头中存储所偏向的线程ID,如果下一次还是该线程获取锁,只需要在对象头Mark Word中去判断一下是否有偏向锁指向它的ID,大大减少了性能的消耗。
什么时候升级为轻量级锁呢?
当有另外一个线程竞争获取这个锁时,由于该锁已经是偏向锁,当发现对象头 Mark Word 中的线程 ID 不是自己的线程 ID,就会进行 CAS 操作获取锁,如果获取成功,直接替换 Mark Word 中的线程 ID 为自己的 ID,该锁会保持偏向锁状态;如果获取锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁。
轻量级锁
轻量级锁是相对于重量级锁而言,轻量级锁不需要申请互斥量,只需要将Mark Word 中的部分字节CAS更新指向栈中锁记录的指针,如果更新成功,则轻量级锁获取成功,记录锁状态为轻量级锁;否则,说明已经有线程获取了轻量级锁,发生了锁竞争,轻量级锁开始自旋。
自旋锁与自适应自旋锁
自旋锁(包括自适应自旋锁)是轻量级锁在升级为重量级锁前做的最后一次挣扎。
在JDK1.6之前设置自旋锁为自旋超过十次,或者等待线程超过cpu核数的2分之一,锁升级为重量级锁;
在JDK1.6后优化为自适应的自旋锁,如果自旋超过一定次数,或者此时有第三个线程来竞争该锁时,锁升级为重量级锁。
重量级锁
重量级锁是如果多个线程同时竞争锁,只会有一个线程得到这把锁,其他线程获取锁失败,不会和轻量级锁进行自旋等待锁被释放,而是直接阻塞没有获取成功的线程。
重量级锁需要操作系统对线程状态的切换,
当锁升级为重量级锁后,未抢到锁的线程都会被阻塞,进入阻塞队列。
总结
synchronized的执行过程:
- 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
- 如果不是,则使用CAS将当前线程的ID替换Mard Word中的线程ID,如果成功则表示当前线程获得偏向锁,置偏向标志位1
- 如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。
- 当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
- 如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
- 如果自旋成功则依然处于轻量级状态。
- 如果自旋失败,则升级为重量级锁。
最新文章
- C# Linq 交集、并集、差集、去重
- Discuz论坛安全加固浅析
- iOS开启隐藏文件以及显示文件方法
- Spring的依赖注入怎么理解
- Linux下Ruby开发配置
- Bone.io是一个轻量级的框架构建高性能实时单页HTML5应用程序
- hdu4393 Throw nails(只用模拟前面500来次,后面根据速度、位置、id值排序即可)
- VS2010中安装AjaxControlToolkit
- shc加密shell脚本
- day01_使用Android Studio创建第一个Android项目
- Python3-Cookbook总结 - 第三章:数字日期和时间
- angular4 使用swiper 首次加载问题(一)
- 嵌入式单片机STM32应用技术(课本)
- 树莓派进阶之路 (037) - 设置树莓派3 B+的静态IP
- JS设计模式(4)迭代器模式
- cocos2d-js 小知识
- [SDOI2010] 外星千足虫
- mybatis之注解式开发之关联查询
- ibatis in的用法
- JSP (tomcat 内置对象)
热门文章
- BIM技术基础-Revit2019建筑
- Chapter Zero 0.1.3 其他单元设备以及运作流程
- ArcGIS制作MobileCache
- hihocoder 1631
- 作业day03吴童
- Spring Cloud Alibaba+Nacos搭建微服务架构
- js location API All In One
- ES Next &; Arrow function &; Promise &; Iterator &; Generator yield &; Async Await
- SVG &; Sprite &; symbol &; use
- 「NGK每日快讯」12.11日NGK公链第38期官方快讯!