微信引流主动被加软件,网站seo优化很好徐州百都网络点赞,同城新闻app有哪些,那个网站做调查问卷能赚钱一、概述研究java对象头的目的是详细分析Java的synchronized锁的升级过程#xff0c;因为synchronized在锁升级的时候#xff0c;就是依赖对象头的信息来决定的。本博文针对64位的操作系统来对Java对象头进行详解。二、详细分析1. 用户态与内核态内核态与用户态是操作系统的两…一、概述 研究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操作原理 CAS全拼又叫做compareAndSwap从名字上的意思就知道是比较交换的意思。它包含 3 个参数 CASVENV表示要更新变量的值E表示预期值N表示新值。仅当 V值等于E值时才会将V的值设为N如果V值和E值不同则说明已经有其他线程做两个更新则当前线程则什么都不做。最后CAS 返回当前V的真实值。隐藏的问题以及解决办法参考前文《我的jdk源码二十四AtomicInteger类和CAS机制》。 在linux_x86这个具体系统平台的代码中源码如下 由两个红框的内容可以看到底层的实现是CPU指令原语lock和cmpxchg组合执行的值得一提的是cmpxchg指令虽然支持CAS却并不是原子性的操作所以我们看下LOCK_IF_MP是怎么操作的实现的源码如下 MP是multi processor的缩写意为多处理器。所以在多核处理时lock指令会锁住系统总线进而锁定一个北桥信号。java中锁底层基本都是利用lock汇编指令完成。 3. JOL工具 (1) Java Object Layout引入jar包就可以在代码中观察跟踪synchronized的琐升级过程。 (2) 代码实现如下 (3) 打印结果如下 通过上面可以清晰的看到一个对象在内存之中有哪些值由哪些东西构成。 (4) 对象在内存中的存储布局 mackword存放琐标志位、偏向锁位、线程ID、分代年龄等内容下面详细解读。 Klassword也就是calss pointer存储对象所属类的地址就是为了标记到底是什么类的实例。 instance data保存成员变量实例对象。 padding是为了保证整个内容加起来能被8个字节(Byte)整除而填充的空间JVM读数据是一块一块读的这样做效率是最高的。 length如果对象是数组需要存储数组长度。 (5) 根据观察到的对象头结构如下 详细解释 (1) 当我们创建一个无锁态对象的时候25位没有用31位装的identity Hashcode但是只有在被调用的时候才填充没有调用的时候是空的1位没有使用的4位分代年龄(解释在下面)1位偏向锁位2位锁标志位。 (2) 偏向锁的时候54位存下当前线程的ID2位存批量撤销Epoch1位没有使用4位分代年龄1位偏向锁位2位锁标志位。 (3) 自旋锁62位指向线程中的Lock Record的指针。Lock Record与锁重入有关synchronize默认是可重入的。自旋锁在竞争锁的时候会在自己的内存中创建一个Lock Record对象抢到锁对象的资源时锁对象头存的就是这个线程的Lock Record对象的指针所以在重入的时候会再创建一个Lock Record对象利用Lock Record来记录到底琐了多少次。解锁的时候就将一个Lock Record移除。 (4) 重量级琐重量级琐是在C代码层面进行的会生成一个ObjectMonitor对象这个对象中记录了一系列的队列如下图 (5) 分代年龄JVM有10种垃圾回收器前面7种都涉及分代年龄采用分代算法。当我们创建一个对象的时候把它放在年轻代中每经过一次垃圾回收后年龄就1也就是垃圾回收无法回收掉这个对象它的年龄就会不断的增长到达15因为4个字节最大为15就转到老龄代年轻代的回收就不再对它进行回收。 4. synchronized琐升级过程 注意 (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版本都支持如下图 第二类以-X开头的叫做非标准参数是有版本差异的有的版本支持有的版本不支持。 第三类以-XX开头的是可以配置的参数。 利用以下命令打印所有可以设置参数的项和值打印出来 利用以下命令可以查看一共有多少行 利用以下命令可以查看所有和偏向锁有关系的参数 上图解释我们在创建一个对象的时候即使默认启用了偏向锁创建出来的对象也是无琐的但是如果我们在创建对象前先设置5秒的延迟再创建出来的对象就是偏向锁状态的也就是匿名偏向锁也就是上面琐升级过程图中的另一种情况。具体操作如下 代码如下 运行结果如下三、总结 本文主要介绍了java对象头的组成与synchronized升级过程深入底层了解原理很多细节在文中需要各位仔细研读 更多精彩内容敬请扫描下方二维码关注我的微信公众号【Java觉浅】获取第一时间更新哦http://weixin.qq.com/r/xx3v9_7EY7McraqU90jV (二维码自动识别)