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

郑州专业制作网站费用网站竞价推广怎么做

郑州专业制作网站费用,网站竞价推广怎么做,传统网站网站,河南省建设工程一体化平台简介 锁升级,也可以理解为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://www.dtcms.com/wzjs/18623.html

相关文章:

  • 网站ui设计要点网站推广方案策划书2000
  • 如何攻击织梦做的网站方法网络推广优化工具
  • 硅云wordpress多站点微信软文怎么写
  • 软件开发找谁网站优化的方法
  • 专业网站建设哪里好哈尔滨seo网络推广
  • wordpress植物网站百度云盘资源
  • 专门做衣服的网站百度指数功能
  • 网页广告图seo搜索优化公司报价
  • 在自己的网站做百度搜索框百度推广营销
  • 做卡通的素材网站优化设计答案六年级上册语文
  • 哈尔滨嘟嘟网络靠谱吗网页优化建议
  • 北京网站制作报价链接点击量软件
  • 成都广告公司排行seo免费资源大全
  • 网站开发讲座百度有免费推广广告
  • 最早做美食团购的网站百度推广系统营销平台
  • 深圳 商城 网站建设新闻媒体发布平台
  • 几台服务器做集群网站全国疫情最新消息今天实时
  • php酒店网站源码武汉全网营销推广公司
  • 微信网页版登陆入口长沙优化科技
  • 项目网站建设方案百度seo关键词优化公司
  • 手机有软件做ppt下载网站有哪些内容吗百度推广合作
  • 西二旗网站建设免费推广网站大全下载
  • 南昌集团网站建设百度财报q3
  • 北京海淀中关村找工作网站优化师的工作内容
  • 麻城做网站第一设计
  • 中英 网站模板 带手机版关键词seo优化
  • 南京专业网站设计公司湖南网络推广服务
  • 深圳做网站de公司网站关键词优化排名公司
  • 佛山专业做网站公司seo实训报告
  • 做网站怎么防止被网警查到杭州百度