首页 > 其他分享 >描述一下锁的四种状态及升级过程?

描述一下锁的四种状态及升级过程?

时间:2023-03-06 20:36:04浏览次数:50  
标签:对象 升级 MarkWord 线程 偏向 四种 重量级 轻量级 描述

 

1、锁的四种状态

无锁、偏向锁、轻量级锁、重量级锁

2、Java对象头描述

以下为32位对象头描述
在这里插入图片描述以下为64位对象头描述
在这里插入图片描述

3、锁的升级过程(Synchronized加锁/膨胀流程)

1)简单过程如下图

在这里插入图片描述

2)详细过程

当线程访问同步代码块时,首先判断当前锁状态是否为可偏向状态(对象头中偏向锁=1,锁标志=01)
在JDK1.6以上默认开启,开启后程序启动几秒后才会被激活

(1)偏向锁

如果是可偏向状态,检查MarkWord存储的是否是当前线程ID

  • 是,获得偏向锁,执行同步代码块
  • 不是,CAS操作竞争锁,替换线程ID
    • 替换成功,MarkWord的线程ID设置为当前线程ID(线程复用),执行同步代码块
    • 替换失败,锁撤销,升级为轻量级锁
      同一类对象多次撤销升级达到阈值20,则偏向锁认为,后面的锁需要重新偏向新的线程(批量重偏向)
      如果阈值达到40次,则偏向锁认为偏向锁撤销过于频繁,后面直接使用轻量级锁

(2)轻量级锁

升级为轻量级锁的情况

  • 如果不是可偏向状态,直接升级为轻量级锁
  • 偏向锁撤销次数过多

加锁时,会在当前线程栈帧中划出一块空间,作为该锁记录,并且将锁对象MarkWord复制到该锁记录中,CAS操作将MarkWord更新为该锁记录的指针,锁记录中的owner指针指向对象头的MarkWord。

  • 更新成功,MarkWord锁标志位为00,表示轻量级锁状态
  • 更新失败,检查锁对象MarkWord是否指向当前线程栈帧中的锁记录
    • 是,表示锁重入,在当前线程栈帧中锁记录+1
    • 否,自旋等待(默认10次),等待次数达到阈值,升级为重量级锁

(3)重量级锁

升级为重量级锁的情况

  • 竞争加剧,CAS自旋到一定次数升级为重量级锁
  • 自旋线程数超过CPU核数的一半, 1.6之后,加入自适应自旋Adapative Self Spinning,JVM自己控制

获取锁成功,进入EntryList(获取锁的缓冲区、入口)

  • 在调用wait方法后,会进入等待唤醒队列(WaitSet)等待
  • 在调用notify方法后,则可能进入EntryList
    获取锁失败,进入一个等待拿锁队列(cxq)等待

具体重量级锁加锁过程:
1、分配⼀个ObjectMonitor对象,把MarkWord锁标志置为‘10’,然后MarkWord存储指向ObjectMonitor对象的指针。ObjectMonitor对象有两个队列和⼀个指针,每个需要获取锁的线程都包装成ObjectWaiter对象
2、多个线程同时执行同⼀段同步代码时,ObjectWaiter先进⼊EntryList队列,当某个线程获取到对象的monitor以后进⼊Owner区域,并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count+1

说明:
monitor:每个Java对象都有一把锁,称为内部锁或monitor锁
owner,指向的是当前获得线程的地址,用来判断当前锁是被哪个线程持有

4、拓展

1)synchronized效率低?

用户态:偏向锁、轻量级锁
内核态:重量级锁

首先来了解下synchronized重量级锁实现原理?
  通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本质又是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高。
  在JDK6以前,只有重量级锁,阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成,这种状态切换需要耗费处理器时间。
  在JDK6中,为了提高性能,引入了偏向锁和轻量级锁。

2)为什么要有偏向锁?

大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了减少线程获得锁的代价,所以引入了偏向锁

3)为什么要有重量级锁?

自旋锁消耗CPU资源,重量级锁有等待队列,不会消耗CPU资源

4)偏向锁是否一定比自旋锁效率高?

不一定,在多线程竞争情况下,偏向锁会涉及锁撤销,这时候应该直接使用自旋锁

5)锁重入

重入次数必须记录,才能知道要解锁几次

  • 轻量级锁,记录在线程栈,每插入一次,LockRecord+1
  • 重量级锁,记录在ObjectMonitor字段上

6)Hopspot对象头就是MarkWord?

不是的,Hopspot对象头主要包括两部分数据:MarkWord(标记字段) 和 classPointer(类指针)

7)锁可以降级?

不行的,是一个不可逆的过程,主要是为了提高获得锁和释放锁的效率

8)锁对比,适用场景?

偏向锁:适用于一个线程,不会有锁消耗,锁撤销
轻量级锁:适用于多个线程竞争,但同步代码块执行快的情况下,因为自旋会消耗CPU
重量级锁:适用于多个线程竞争,但同步代码块执行慢的情况下,不消耗CPU,可以提高吞吐量

标签:对象,升级,MarkWord,线程,偏向,四种,重量级,轻量级,描述
From: https://www.cnblogs.com/huozhonghun/p/17185298.html

相关文章

  • 微服务引擎 MSE 企业版全新升级
    作者:流士随着企业应用大规模云上迁徙与应用微服务化步伐加快,微服务治理的重要性对企业不言而喻,但微服务治理本身的规范化与标准化尚未形成,导致很多企业在微服务治理方面......
  • CentOS 升级内核的三种方式(yum/rpm/源码)
    CentOS升级内核的三种方式(yum/rpm/源码)在CentOS使用过程中,难免需要升级内核,但有时候因为源码编译依赖问题,不一定所有程序都支持最新内核版本,所以以下将介绍三种升级内......
  • Static的一些描述
    Staticstatic表示静态,是JAVA中的一个修饰符,可以修饰成员方法,成员变量被static修饰的成员变量,叫做静态变量静态变量特点:1.被该类所有对象共享所有对象都用同一个......
  • JavaScript判断变量类型的四种方法
    typeof(根据二进制判断):常用于判断基础数据类型,对于引用数据类型除了function返回‘function’,其余都返回‘object’(typeofnull===object)instanceof:主要用于区分引......
  • 使用ELRepo升级CentOS内核
    在腾讯云中部署了一些服务器,操作系统使用的是CentOS7.6,但是其默认内核版本较低,现使用ELRepo对CentOS的内核进行升级。操作环境服务器:腾讯云轻量应用服务器操作系统:Cent......
  • eyoucms 首页以及列表页内容调用标题、关键词、描述
    1、首页调用标题、关键词、描述123<title>{eyou:global name='web_title' /}</title><metaname="description" content="{eyou:globalname='web_descr......
  • Activity的四种启动模式详解
    Activity的启动模式1.启动模式的类别标准模式(standard)栈顶复用模式(singleTop)栈内复用模式(singleTask)单例模式(singleInstance)2.任务栈任务栈Task,是一种用来放置......
  • 详解Prometheus四种指标类型
    指标是用来衡量性能、消耗、效率和许多其他软件属性随时间的变化趋势。它们允许工程师通过警报和仪表盘来监控一系列测量值的演变(如CPU或内存使用量、请求持续时间、延迟......
  • 2.JavaScript如何实现异步编程,可以详细描述EventLoop机制
    单线程和异步js的任务分为同步和异步两种,它们的处理方式也不同,同步任务是直接在主线程上排队执行,异步任务则会被放在任务队列中,若有多个任务(异步任务)则要在任务队列中排......
  • 证监会发布新规,投资者个人信息保护要求再升级
    3月3日,证监会发布《证券期货业网络和信息安全管理办法》(以下简称《办法》),将于2023年5月1日起正式实施。《办法》共八章七十五条,全面覆盖了包括证券期货关键信息基础设施运营......