当前位置: 首页 > wzjs >正文

做ppt的素材免费网站建网站备案需要的材料

做ppt的素材免费网站,建网站备案需要的材料,做微信推送网站,手机制作视频软件app有哪些简介 锁升级,也可以理解为synchronized关键字的原理,是Java1.6中对synchronized关键字做的优化,锁升级涉及到对象的内存布局,在这里总结一下锁升级的过程和过程中对象内存布局的变化。 锁升级 锁升级:在JDK 1.6之前…

简介

锁升级,也可以理解为synchronized关键字的原理,是Java1.6中对synchronized关键字做的优化,锁升级涉及到对象的内存布局,在这里总结一下锁升级的过程和过程中对象内存布局的变化。

锁升级

锁升级:在JDK 1.6之前,Java内置锁还是一个重量级锁,是一个效率比较低下的锁,在JDK 1.6之后,为了提高锁的获取与释放效率,对synchronized的实现进行了优化,引入了偏向锁和轻量级锁,从此Java内置锁就有4种状态,级别由低到高依次为:无锁、偏向锁、轻量级锁和重量级锁。锁的4种状态会随着竞争的情况逐渐升级,而且是不可逆的过程,即不可降级。

锁升级的过程:

  • 无锁:对象刚创建的时候,处于无锁状态

  • 偏向锁:只有一个线程获取锁时,发现锁是无锁状态并且是可偏向的,会尝试把自己的线程id写入到对象头中,表示当前的锁是一个偏向锁。偏向锁的执行效率和无锁几乎相同,因为它只有第一次获取锁时,使用CAS算法,将线程ID设置到对象头中,之后,如果发现这个线程ID是自己,直接获取锁。由于偏向锁是为单个线程设计的,所以线程不会主动释放偏向锁,只有遇到其他线程尝试竞争偏向锁时,偏向锁才会被撤销。

  • 轻量级锁:偏向锁在有锁竞争时升级为轻量级锁。在轻量级锁下,没有获取到锁的线程不会阻塞而是自旋,如果同步代码块的执行时间较短并且竞争不激烈,自旋比阻塞导致的线程上下文切换带来的消耗要小。所以轻量级锁是在竞争不激烈的情况下使用自旋代替互斥。

  • 重量级锁:线程的自旋次数超过阈值之后,锁由轻量级锁升级为重量级锁,此时等待锁的线程都会进入阻塞状态,并且存放于一个监视器中,重量级锁的底层依赖monitor机制。

偏向锁的延迟加载:虚拟机在启动5秒之内创建的锁是轻量级锁,5秒之后创建的锁为偏向锁,这是虚拟机的优化措施。JVM会在一个安全点暂停持有偏向锁的线程,然后将用作锁的对象头中的偏向锁标识撤销,在这个安全点所有线程都停止工作,所以偏向锁的撤销可能会导致STW(世界暂停),影响服务的稳定性。

锁的升级是由JVM来进行的。

对象的内存布局

对象的内存布局描述了对象的数据结构。

查看java对象内存布局的方式:在项目中添加jar包 jol-core,jol的含义是java object layout,它是openjdk提供的工具包,可以用来查看对象的内存布局。

入门案例

查看一个Object类型的对象在内存中的布局,这算是最简单的对象了

步骤:第一步添加依赖、第二步打印对象的内存布局

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version>
</dependency>
public static void main(String[] args) {Object obj = new Object();System.out.println(ClassLayout.parseInstance(obj).toPrintable());
}

结果:

在这里插入图片描述

jol依赖中的相关API:

  • ClassLayout:public class ClassLayout:存储了java对象的布局信息
    • parseInstance方法:public static ClassLayout parseInstance(Object instance, Layouter layouter):解析java对象的布局信息,生成ClassLayout对象
    • toPrintable方法:public String toPrintable():生成存储了布局信息的字符串

解析对象的内存布局

一个java对象在内存中包含三个部分:对象头、实例数据、对齐字节。

  • 对象头:存储对象的属性
  • 实例数据:也就是类中的成员变量,如果一个类有父类,实例数据也包含父类的成员变量。
  • 对齐字节:JVM要求java对象占的内存大小应该是CPU字长的倍数,所以后面有几个字节用于把对象的大小补齐至8的倍数

对象头

对象头的组成部分:对象头由mark word、类指针组成,如果对象是一个数组对象,还会有一个数组长度字段。

  • mark word:存储对象运行时的数据,如哈希值、gc分代年龄等,mark word中的数据会在运行时进行修改。mark word的长度是jvm一个字长的大小,也就是说32位JVM的Mark word为32位,64位JVM的Mark word为64位。

  • 类指针:class pointer,指向类对象的指针,jvm通过这个指针确定对象是哪个类的实例

  • 数组长度:array length,如果对象是一个数组,对象头还需要存储数组的长度

mark word

mark word是对象头中最复杂的地方,它存储的数据在运行时会被修改,例如,锁标志位、对象分代年龄、哈希值等,相比之下,类指针和数组长度都是常量,在运行时不会改变。

mark word中存储的数据:(截了两张网上的图)

  • 在64位的虚拟机上:

在这里插入图片描述

  • 在32位的虚拟机上:

在这里插入图片描述

mark word中存储的数据:不考虑对象的状态,只描述对象中存储的数据、数据的长度、数据的位置 (这里是基于64位的虚拟机)

  • 锁标志位:2bit,存放在第一个字节的最后两位,01表示无锁,00表示轻量级锁,10表示重量级锁,11是gc标记
  • 偏向锁标识:1bit,biased_lock,存放在lock之后,只占一个二进制位,为1时表示对象启用偏向锁,为0时表示对象没有偏向锁
  • 对象分代年龄:4bit,存储在biased_lock之后,在gc中,如果对象在survivor区复制一次,年龄增加1,当对象达到设定的阈值时,将会晋升到老年代
  • 哈希值:31bit,调用继承自Object类的hashCode方法后,生成的哈希值会存储到对象头中
  • 指向持有偏向锁的线程的指针:54bit,threadId
  • 偏向时间戳:2bit,epoch,记录线程获取了几次偏向锁
  • 在轻量级锁的状态下指向栈中锁的记录的指针:ptr_to_lock_record:62bit
  • 在重量级锁的状态下指向监视器(管程monitor)的指针:ptr_to_heavyweight_monitor:62bit

为什么偏向锁状态下mark word中存的是线程id,轻量级锁状态下mark word中存的是执行栈中锁记录的指针?如果是轻量级锁,当线程尝试获取锁时,若对象未被锁定,JVM会在该线程的栈帧中创建一个锁记录,并将对象的mark word复制到其中,随后,jvm使用cas操作将mark word更新为指向该锁记录的指针。这么做的好处是什么?支持锁重入:锁记录可以记录重入次数,线程每次重入锁时,锁记录会记录相关信息,释放锁时则减少重入次数,直到完全释放。

类指针

指向类对象的指针,jvm通过这个指针确定对象是哪个类的实例,

数组长度

如果是数组对象,对象头中会存储数组长度

成员变量

存储对象中的成员变量,就是用户可以通过getter、setter方法访问到的数据,要注意,如果一个类有父类,父类中成员变量的值也会被存储在这里。

对象的内存布局-实际案例

案例1:最简单的对象

以入门案例中的Object对象为例:
在这里插入图片描述

打印结果讲解:

  • 第一行:对象的类型,这里是Object类型
  • 第二行到倒数第三行之间是一个表格
    • 表格中的字段:
      • OFFSET:偏移量,对象头中的字段相对于对象头的偏移量,所以第一个字节的偏移量是0
      • SIZE:长度,以字节为单位
      • TYPE DESCRIPTION:类型描述,描述了对象中存储了什么数据
      • VALUE:每个字节中存储的数据分别用十六进制、二进制、和十进制进行了描述
    • 表格中的内容:
      • object header:表示存储的数据是对象头
      • loss due to the next object alignment:为了内存对齐而丢失一部分内存空间
  • 倒数第二行:Instance size,对象大小
  • 倒数第二行:Space losses,丢失的空间,这里为了内存对齐,有4字节的空间没有用。internal表示对象头内丢失的字节,external表示对象头外丢失的字节

要注意:无论是Windows系统,还是Linux系统,都是采用的小端存储法,在低地址存储低位数据。

详细讲解:
在这里插入图片描述

案例2:存储了数据的对象

一个存储了数据的对象:对象中存储了一个String、一个Integer、一个boolean值在这里插入图片描述

案例3:数组对象

一个int类型的数组类型的对象的内存布局,数组的长度是8

在这里插入图片描述

案例4:类对象

一个类对象的内存布局:

在这里插入图片描述

案例5:哈希值在对象头中的存储

在对象的正常状态下,从第二个字节开始,使用31比特位来存储哈希值

代码:

Object obj = new Object();
System.out.println("Integer.toBinaryString(obj.hashCode()) = " + Integer.toBinaryString(obj.hashCode()));
System.out.println(ClassLayout.parseInstance(obj).toPrintable());

执行结果:

在这里插入图片描述

结果解析:

  • 系统采用的是小端存储法,低地址存放的是低位数据
  • 哈希值的长度是31位,从第二个字节开始,到第五个字节的后7位,都是存储的哈希值,第五个字节的第一个比特位没有使用
  • 第五个字节的后7位对应的是哈希值的开头,第四个字节紧随其后,依次类推

解析内存布局时涉及到的知识点

大端法和小端法

大端法和小端法:描述了跨越多个字节的数据在内存中的存储方式

  • 小端法:低地址存放数据低位
  • 大端法:低地址存放数据高位

要注意,数据在存放时,字节是基本存储单元,无论是大端法还是小端法,存放数据的顺序都是从低地址到高地址,区别在于低地址存放低位数据还是高位数据。

Intel处理器采用小端存储法,Windows系统和Linux系统采用的都是Intel处理器。

内存对齐

CPU访问内存时,并不是逐个字节访问,而是以字长(word size)为单位访问,所以数据应该尽可能的放在内存地址是字长的倍数的位置,如果访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存访问仅需要一次访问,内存对齐是使用空间换时间,提高了速度。内存对齐是由编译器来完成的

对齐系数:系数是指单项式中的数字因数,对齐系数是编译器做内存对齐时需要使用的常量,每个特定平台上的编译器都有自己的默认"对齐系数",常用平台默认对齐系数:32位系统对齐系数是4,代表4字节,64位系统对齐系数是8

指针压缩

在64位的虚拟机上并且堆内存小于32G时默认开启指针压缩,指向堆内存的指针会由64位被压缩到32位

指针压缩的jvm参数:-XX:+UseCompressedOops // java虚拟机的参数中, + 表示开启, - 表示关闭

案例1:查看虚拟机的参数

在命令行执行命令 java -XX:+PrintCommandLineFlags -version,也可以把这个命令添加到java程序中

打印结果:

-XX:InitialHeapSize=265280448 -XX:MaxHeapSize=4244487168 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops  
-XX:UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

结果解析:

  • InitialHeapSize:初始化堆内存大小,256M
  • MaxHeapSize:最大堆内存大小,4G
  • PrintCommandLineFlags:打印命令行参数
  • +UseCompressedClassPointers:压缩指向类对象的指针
  • +UseCompressedOops:压缩普通指针,oop,表示ordinary object pointers,普通java对象指针
案例2:关闭指针压缩

为Java程序添加虚拟机参数:-XX:-UseCompressedClassPointers -XX:-UseCompressedOops

查看结果:
在这里插入图片描述

结果解析:对象头占16个字节。因为没有开启指针压缩,锁指向类对象的指针是8个字节

锁升级过程中对象内存布局的变化

偏向锁

创建偏向锁的方式:

  • 第一种:加锁之前先让线程睡5秒。虚拟机在启动的5秒内创建的锁都不是偏向锁,这是虚拟机的一种优化措施
  • 第二种:加上JVM的运行参数,关闭偏向锁的延迟,相关参数:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0

案例:

public static void main(String[] args){try {Thread.sleep(6000);} catch (InterruptedException e) {throw new RuntimeException(e);}// 程序启动5秒之后再创建对象Object LOCK = new Object();System.out.println("执行同步代码块之前: \n" + ClassLayout.parseInstance(LOCK).toPrintable());synchronized (LOCK) {System.out.println("获得锁的线程: \n"+ ClassLayout.parseInstance(LOCK).toPrintable());}System.out.println("执行同步代码块之后: \n" + ClassLayout.parseInstance(LOCK).toPrintable());
}

结果解析:

  • 执行同步代码块之前的对象:

在这里插入图片描述

  • 获得锁的线程

在这里插入图片描述

  • 执行同步代码块之后,线程偏向锁不会主动释放偏向锁,打印执行同步代码块之后的内存布局,和获得锁时的内存布局一模一样。

轻量级锁

案例:

private static final Object LOCK = new Object();public static void main(String[] args) {System.out.println("执行同步代码块之前: \n" + ClassLayout.parseInstance(LOCK).toPrintable());new Thread(LightWightLockTest::sync).start();try {Thread.sleep(1000L);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("执行同步代码块之后: \n" + ClassLayout.parseInstance(LOCK).toPrintable());
}private static void sync() {synchronized (LOCK) {System.out.println("获得锁的线程: \n" + Thread.currentThread().getName() + ": \n"+ ClassLayout.parseInstance(LOCK).toPrintable());}
}

案例讲解:在同步代码块内打印对象的内存布局,可以看到轻量级锁状态下对象头内的数据

在这里插入图片描述

同步代码块退出后,等1秒钟,再次打印锁对象的内存布局,发现轻量级锁已经变成无锁,指针数据也被清除。

重量级锁

案例:

private static final Object LOCK = new Object();public static void main(String[] args) {System.out.println("执行同步代码块之前: \n" + ClassLayout.parseInstance(LOCK).toPrintable());for (int i = 0; i < 2; i++) {new Thread(HeavyWeightTest::sync).start();}try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("执行同步代码块之后: \n"+ ClassLayout.parseInstance(LOCK).toPrintable());}private static void sync() {synchronized (LOCK) {System.out.println("获得锁的线程: \n"+ Thread.currentThread().getName() + ": \n"+ ClassLayout.parseInstance(LOCK).toPrintable());}
}

案例讲解:多个线程同时竞争,锁直接由无锁变成重量级锁

在这里插入图片描述

参考

  • https://www.cnblogs.com/mingyueyy/p/13054296.html
  • https://www.cnblogs.com/coderacademy/p/18204403

文章转载自:

http://ITCeBhex.tcpnp.cn
http://vb5VNYXK.tcpnp.cn
http://wPcJRgIH.tcpnp.cn
http://9Nilv23u.tcpnp.cn
http://ztriKtJP.tcpnp.cn
http://45BfquC4.tcpnp.cn
http://FPzDiKjP.tcpnp.cn
http://dQd5cjeE.tcpnp.cn
http://hp8s2Tau.tcpnp.cn
http://696AQUnf.tcpnp.cn
http://Uuab1EVK.tcpnp.cn
http://9qfhw8RM.tcpnp.cn
http://BFCrnVn2.tcpnp.cn
http://HsvQmMiW.tcpnp.cn
http://7VoDE5Ao.tcpnp.cn
http://ERAO2flz.tcpnp.cn
http://j7jYRTkM.tcpnp.cn
http://vTV0M7Ub.tcpnp.cn
http://3bb0LExv.tcpnp.cn
http://Hhom23Ol.tcpnp.cn
http://aYE1Gsfq.tcpnp.cn
http://SgQI5E6A.tcpnp.cn
http://RXU4ip3Z.tcpnp.cn
http://8iJR6YMV.tcpnp.cn
http://mqHEPPhn.tcpnp.cn
http://pIG1Lpg3.tcpnp.cn
http://q6qDsFxs.tcpnp.cn
http://ySkXUZ97.tcpnp.cn
http://7eSB7Mnk.tcpnp.cn
http://kpqsCgQQ.tcpnp.cn
http://www.dtcms.com/wzjs/636364.html

相关文章:

  • 网站的留言怎么做有哪些app软件开发公司
  • 东莞网站网络推广公司ps做网站浏览器预览
  • 网站备案到期了怎么办公司网站建设的工具
  • 个人个案网站 类型网站加入我们页面
  • 南京做中英文网站设计三一国际网站设计
  • 个人网站建站系统长沙旅游攻略景点必去
  • 客户端网站建设文档青岛门户网站建设
  • wordpress 中文工单抖音seo优化系统招商
  • 可以做语文阅读题的网站设计网站源码
  • 做教师章节试题哪个网站express做静态网站
  • 厦门专业建网站无锡建设工程质量监督网站
  • 郑州公司网站建设服务凡科自助建站系统
  • 企业网站的一般要素包括手机企业网站管理系统
  • 公司就我一个网站制作霸屏推广
  • 网站建设公司财务预算重庆网网站建设公司
  • 高端定制网站开发设计建站流程网站建设构架
  • 怎么自己制作属于自己的网站比较有名的个人网站
  • 郑州公司做网站广州番禺各镇分布图
  • 北京的网站制作网站排名下降原因
  • 公众号和网站凡科网免费网站怎么样
  • 找人建网站做网站横幅的软件
  • 个人或主题网站建设实验体会超市设计网站
  • 网站无内容 备案梁志天设计公司官网首页
  • 海南澄迈住房和城乡建设厅网站珠海建设工程交易中心网站
  • 英语培训东莞网站建设建设网站如何挂到网上
  • 网站及其建设的心得体会企业管理咨询服务协议
  • cms网站制作seo推广系统排名榜
  • 南京网站开发招聘微信商城如何开通
  • 长春网站建设长春电梯公司抖音餐厅代运营方案
  • 昆山建设银行网站首页合肥百度 网站建设