java对象头_我的并发编程(二):java对象头以及synchronized升级过程

9a93b083ac91d48e47e528b5417a5262.png

一、概述

研究java对象头的目的是详细分析Java的synchronized锁的升级过程,因为synchronized在锁升级的时候,就是依赖对象头的信息来决定的。本博文针对64位的操作系统来对Java对象头进行详解。

二、详细分析

1. 用户态与内核态

内核态与用户态是操作系统的两种运行级别,当程序运行在3级特权级上时, 就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运 行的特权级,大部分用户直接面对的程序都是运行在用户态;当程序运行在0级特权级上时,就可以称之为运行在内核态。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态。

操作系统对于用户态线程(也叫纤程)的管理是由系统内核kernel来管理的。JVM中的线程与操作系统的原生线程对应关系一般是1:1的关系。对应关系除了1:1,也有m:1,也就是用户态的m个线程只对应内核态中的1个线程;m:n的关系,出现在go语言的协程中。计算机上的程序包括JVM是运行在计算机的用户空间上,运行在用户空间上的程序的特点就是,在进行一些敏感操作(比如网络读写、读写硬盘、内存映射等)的时候,需要通过工作在内核空间的系统内核kernel进行系统调用,这样的目的是使得操作系统更加的健壮。

synchronized什么是重量级琐?申请锁资源的时候需要通过操作系统内核kernel进行系统调用,这个调用过程将会由用户空间切换到内核空间,就是重量级琐;轻量级锁是只在用户空间就完成对用户空间锁的调度管理,直接生成汇编指令,不需要经过系统内核。jdk1.5推出JUC包,利用CAS采用的轻量级锁自旋锁来替代一些需要锁的地方,极大的提高效率。

2. CAS操作原理

ff181207a15ecfb8665177655065acc5.png

CAS全拼又叫做compareAndSwap,从名字上的意思就知道是比较交换的意思。它包含 3 个参数 CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当 V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做两个更新,则当前线程则什么都不做。最后,CAS 返回当前V的真实值。隐藏的问题以及解决办法参考前文《我的jdk源码(二十四):AtomicInteger类和CAS机制》。

在linux_x86这个具体系统平台的代码中源码如下:

ccdb843f79a34529ff75d050a9fe96a1.png

由两个红框的内容可以看到,底层的实现是CPU指令原语lock和cmpxchg组合执行的,值得一提的是cmpxchg指令虽然支持CAS,却并不是原子性的操作,所以我们看下LOCK_IF_MP是怎么操作的,实现的源码如下:

0beab3920d775a4483770f75762a9ccf.png

MP是multi processor的缩写,意为多处理器。所以在多核处理时,lock指令会锁住系统总线,进而锁定一个北桥信号。java中锁底层基本都是利用lock汇编指令完成。

3. JOL工具

(1) Java Object Layout,引入jar包,就可以在代码中观察跟踪synchronized的琐升级过程。

e8a960b8f85006d1bc2a6b2fc9086396.png

(2) 代码实现如下:

0f7e853b780d20057a2a8775b47c87cb.png

(3) 打印结果如下:

5b956ca3110f72d18f4419d0695d507c.png

通过上面可以清晰的看到一个对象在内存之中,有哪些值,由哪些东西构成。

(4) 对象在内存中的存储布局:

d2a285517a614f8625a4cd586dfdcd86.png

mackword:存放琐标志位、偏向锁位、线程ID、分代年龄等内容,下面详细解读。

Klassword:也就是calss pointer,存储对象所属类的地址,就是为了标记到底是什么类的实例。

instance data:保存成员变量实例对象。

padding:是为了保证整个内容加起来能被8个字节(Byte)整除而填充的空间,JVM读数据是一块一块读的,这样做效率是最高的。

length:如果对象是数组,需要存储数组长度。

(5) 根据观察到的对象头结构如下:

48c252242bef6b19abc8930c834c9035.png

详细解释:

(1) 当我们创建一个无锁态对象的时候:25位没有用;31位装的identity Hashcode,但是只有在被调用的时候,才填充,没有调用的时候是空的;1位没有使用的;4位分代年龄(解释在下面);1位偏向锁位;2位锁标志位。

(2) 偏向锁的时候:54位存下当前线程的ID;2位存批量撤销Epoch;1位没有使用;4位分代年龄;1位偏向锁位;2位锁标志位。

(3) 自旋锁:62位指向线程中的Lock Record的指针。Lock Record与锁重入有关,synchronize默认是可重入的。自旋锁在竞争锁的时候,会在自己的内存中创建一个Lock Record对象,抢到锁对象的资源时,锁对象头存的就是这个线程的Lock Record对象的指针,所以在重入的时候,会再创建一个Lock Record对象,利用Lock Record来记录到底琐了多少次。解锁的时候,就将一个Lock Record移除。

(4) 重量级琐:重量级琐是在C++代码层面进行的,会生成一个ObjectMonitor对象,这个对象中记录了一系列的队列,如下图:

8ff1851ae756e8da510ab308531b7624.png

(5) 分代年龄:JVM有10种垃圾回收器,前面7种都涉及分代年龄,采用分代算法。当我们创建一个对象的时候,把它放在年轻代中,每经过一次垃圾回收后年龄就+1,也就是垃圾回收无法回收掉这个对象,它的年龄就会不断的增长,到达15,因为4个字节最大为15,就转到老龄代,年轻代的回收就不再对它进行回收。

4. synchronized琐升级过程

d09a75e84f5bd4995b713b0008e9ff97.png

注意:

(1) 琐升级路线:new -> 偏向锁 -> 轻量级琐(自旋锁、自适应自旋锁) -> 重量级琐

(2) 如果偏向锁没有启动,那么new出来的对象是普通对象;如果偏向锁已经启动,那么new出来的对象就是匿名偏向对象。

(3) 偏向锁什么情况下转为轻量级琐呢?只要有2个线程竞争同一个琐资源,所有线程都升级为轻量级琐,也就是都会自旋抢占琐资源。

(4) 自旋锁在竞争资源的时候,也是CAS操作,用CAS的方式修改琐对象的mackword。

(5) 自旋锁升级为重量级琐需要符合什么条件呢?jdk1.6以前,某个线程自旋次数上限达到默认的10次,会升级为重量级锁,因为一直自旋消耗CPU资源;自旋线程数量达到了默认是系统的CPU核数的1/2的时候,全部升级为重量级琐进入等待队列。jdk1.6之后,jdk提供了自适应自旋,jdk根据每个线程的运行情况来判断是否需要升级。

5. 查看设置的偏向锁参数

JVM参数分为3类:

第一类: 以-开头的,叫做标准参数,所有的JVM版本都支持,如下图:

8c2868ee8b5b954704397365aa8fc828.png

第二类:以-X开头的,叫做非标准参数,是有版本差异的,有的版本支持,有的版本不支持。

d179966b4612025588647fd017579d0a.png

第三类:以-XX开头的,是可以配置的参数。

利用以下命令,打印所有可以设置参数的项和值打印出来:

d1cfdc22be7ce73d76d33dffabc8f4d5.png

利用以下命令,可以查看一共有多少行:

d1e8550aa28e663b7cc29de629e69f56.png

利用以下命令,可以查看所有和偏向锁有关系的参数:

109161286a740bc37f5807e41f0e7d13.png

上图解释我们在创建一个对象的时候,即使默认启用了偏向锁,创建出来的对象也是无琐的,但是如果我们在创建对象前先设置5秒的延迟,再创建出来的对象就是偏向锁状态的,也就是匿名偏向锁,也就是上面琐升级过程图中的另一种情况。具体操作如下:

代码如下:

04e368adf1235db7a674681cd4d161f4.png

运行结果如下:

50ec3dd05b1e350f05d2902935eabb25.png

三、总结

本文主要介绍了java对象头的组成与synchronized升级过程,深入底层了解原理,很多细节在文中,需要各位仔细研读!

更多精彩内容,敬请扫描下方二维码,关注我的微信公众号【Java觉浅】,获取第一时间更新哦!

http://weixin.qq.com/r/xx3v9_7EY7McraqU90jV (二维码自动识别)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】Beagleboard:BeagleBoneBlack

原文网址:http://elinux.org/Beagleboard:BeagleBoneBlack Did you know that elinux.org has Mailing Lists? Please feel free to register today to discuss the wiki in general, request features, etc. etc.. Thanks!--Wmat (talk) Beagleboard:BeagleBoneBl…

剖析IE浏览器子系统的性能权重

来源于InfoQ: 微软IE开发团队性能主管Jason Weber在一篇博 文中介绍了IE浏览器的各个子系统,并通过实验数据展示了不同网站对浏览器子系统的性能影响和权重,InfoQ中文站对相关内容做了整理,希望对 浏览器开发人员和Web应用开发人员…

每年通过率仅1%的“天才考试”,中国到底应不应该学?

▲ 点击查看说起世界上最顶尖的基础教育,新加坡绝对能占一席之地。香港首富李嘉诚是这么评价新加坡教育的:“新加坡采用的教育体系源于英国传统的教育制度,它的私立、私立教育院校及一流大学和国际教育机构全球卓越。”李嘉诚甚至在长孙还没多…

C# VS生成后事件命令行

“ 引言部分,总领全篇文章的中心内容。”01—前言Visual Studio中,可以在项目-》属性-》生成事件-》生成后事件命令行(O):中设置项目生成后执行的脚本,从而实现项目文件生产后的自动部署。如下图所示:02—自…

mysql binlog 大数据_后起之秀 | MySQL Binlog增量同步工具go-mysql-transfer实现详解

一、 概述工作需要研究了下阿里开源的MySQL Binlog增量订阅消费组件canal,其功能强大、运行稳定,但是有些方面不是太符合需求,主要有如下三点:需要自己编写客户端来消费canal解析到的数据server-client模式,需要同时部…

如何备份服务器日志到其他服务器_KIWI Syslog日志服务器搭建及配置

认地,kiwi使用UDP 514端口接收日志数据,安装成功后即可接收日志使用命令netstat –ano查看服务器监听状态,如果服务没起来,则重新启动服务Kiwi Syslog Daemon任务:把当天的日志保存在G:event,历史日志保存在…

Dapr牵手.NET学习笔记:状态管理进阶(二)

为了防止并发对数据修改造成差异,dapr使用了etag标签来作为版本号,对数据修改进行验证。下面是对etag的一个demoappsettings.json中的url配置"StateUrl": "http://localhost:3500/v1.0/state/statestore"在PaymentSystem项目中添加两…

这三位同学的名字绝了!笑得肚子疼......

1 这三位同学的名字绝了!▼2 我是一只小海豹我在假装跷跷板▼3 单身狗受到暴击▼4 小宝宝真可怜打针打出了条件反射▼5 每生成一个验证码都有一位程序员......▼6 虽然腿短但是人家跑得快啊▼7 内容引起极度舒适▼你点的每个赞,我都认真当成了喜欢…

从Hadoop框架与MapReduce模式中谈海量数据处理(含淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理前言几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇,而神奇的东西常能勾起我的兴趣,在看过介绍它们的文…

WPF过渡面板

WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织欢迎转发、分享、点赞、在看,谢谢~。 前言效果投稿来源于-郑竣僖 QQ:41130958301—效果预览效果预览(更多效果请下载源码体验):一、Tra…

UScript中的Pow函数

这些天越来越发现数学的重要和妙趣了, 由于一些地方需要使用指数次幂来实现更好的效果, 想当然地去找pow函数,把Object和Actor翻了个底朝天 。。。 结果可想而知, 也正好,尝试了一把UScript和C的混编,但搜一…

哪些才是对女朋友的有效关心,来学习一下~

1 这本书真好,在哪里才能买得到呢?2 求求你,不要抢我的小毛虫!3 所有的乘客请系好安全带4 小朋友非常可爱了5 字幕组真的尽力了!6 学习了7 10月16日,平安南京 根据真实接警经历,发布一则警示案例…

fabric 转账_Fabric 学习笔记-架构初探

本文介绍了Fabric的架构,以及通过一个简单的Demo来熟悉整个交易流程。Hyperledger fabric V1.0的架构如下图所示:application提供各种语言的SDK接口。membership也就是fabric-ca提供成员服务,用来管理身份,提供授权和认证。peer负…

多个goruntine 性能变慢_提高 JavaScript 性能的 12 个技巧

作者丨Liz Parody在创建 Web 应用程序时应始终考虑性能。为了帮助你开始,本文列举了有效提高应用程序性能的 12 种方法。性能是创建网页或应用程序时最重要的一个方面。没有人想要应用程序崩溃或者网页无法加载,或者用户的等待时间很长。根据 Kissmetric…

#celery#周期性任务

2019独角兽企业重金招聘Python工程师标准>>> 玩了一个星期的clannad,是时候干点事了。 折腾了下celery周期性任务: celery提供了一个叫celery beat的服务,用于定时驱使worker执行任务。也就是说,如果本地没有活动的wor…

WTMPlus 1.1 发布

点击上方蓝字关注我们1.1版本WTMPlus上线一个多月以来,得到了越来越多用户的喜爱。虽然1.0版本还有不少问题,但是它的核心理念和功能受到了用户的认可。1.1版本修复了大量用户反馈的易用性的问题和系统Bug,并且加入了强悍的图表工具。图表编辑…

4部“教材级”纪录片,有生之年必看系列!

全世界只有3.14 % 的人关注了爆炸吧知识纪录片是以真实生活为创作素材,以真人真事为表现对象,并对其进行艺术的加工与展现的,以展现真实为本质,并用真实引发人们思考的电影或电视艺术形式。好的纪录片就像打开了一扇新世界的大门&…

Java 操作POI 之复制sheet页

2019独角兽企业重金招聘Python工程师标准>>> 来点干货直接上代码,就不细说了 package com.qs.web.tools.core.excel; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.poi.hssf.us…

Serverless 落地实践

.Net Core Serverless初体验什么是ServerlessServerless 是一个当今软件世界中比较新的话题。它并没有一个普遍公认的权威定义,每个人每个企业对它的解释可能都有不同,而 Serverless 正是在这种情况下不断发发展的。但是就算如此,有一些 Serv…

KOFLive Beta Daily-Scrum 9

组 员今天的工作进 度问 题明天的计划田 飞Work Item 38911:角色四照片拍摄 Work Item 38897:键盘输入人物四的图片已经导入,键盘三个连键检测完成还剩最后一个连键的检测Work Item 38911:拍摄人物角色五付 浩Work Item 37741:游戏主模块 Work Item 3889…