Java锁升级的实现过程

对象内存布局

Java对象在内存中存储的布局可以分为3块区域: 对象头、实例数据、对齐填充。

对象头,分为两个部分,第一个部分存储对象自身的运行时数据,又称为Mark Word,32位虚拟机占32bit,64位虚拟机占64bit。如图所示,不同锁状态下,Mark Word的结构,理解下面要介绍的各种锁,和锁升级过程,都需要先充分了解Mark Word的结构。

第二部分是类型指针,指向类元数据指针,虚拟机通过此指针,确定该对象属于那个类的实例。

轻量级锁

轻量级锁是相对于重量级锁(Synchrnoized)而言的,本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。

轻量级锁的获取

线程进入同步块时,如果此同步对象没有被锁定(即锁标志位为01,是否为偏向锁为0),虚拟机在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的一个Mark Word的copy

然后虚拟机使用CAS操作,尝试将Mark World更新为指向Lock Record的指针,如果更新成功,那么线程拥有了该对象的锁,并且将锁标志位置位00,如图所示

一旦有两条以上的线程抢占该锁,轻量级锁会升级为重量级锁。锁标志位置为10,Mark Word存储的就是指向重量级锁的指针

轻量级锁释

  • 放如果对象的Mark Word仍然指向着线程的锁记录, 那就用CAS操作把对象当前的Mark Word和线程中复制的Displaced Mark Word替换回来, 如果替换成功, 整个同步过程就完成了。
  • 如果替换失败, 说明有其他线程尝试过获取该锁,轻量级锁膨胀为重量级锁,那就要在释放锁的同时, 唤醒被挂起的线程。

偏向锁

引入偏向锁的目的是在没有多线程竞争的前提下,进一步减少线程同步的性能消耗。

偏向锁的获取

开启偏向锁模式后,锁第一次被线程获取的时候,虚拟机会把对象头中是否为偏向锁的标志位设位0,同时使用CAS操作把获取到这个锁的线程的ID记录在对象的Mark Word之中。

当有另外一个线程去尝试获取这个锁时, 偏向模式就宣告结束。 根据锁对象目前是否处于被锁定的状态, 撤销偏向( Revoke Bias) 后恢复到未锁定( 标志位为“01”)或轻量级锁定( 标志位为“00”) 的状态

偏向锁的释放

偏向锁,并没有显式的锁释放过程,主要依靠锁的批量再偏向(Bulk Rebias)机制实现锁释放。

该机制的主要工作原理如下:

  • 引入一个概念 epoch, 其本质是一个时间戳 , 代表了偏向锁的有效性,从前文描述的对象头结构中可以看到, epoch 存储在可偏向对象的 MarkWord 中。
  • 除了对象中的 epoch, 对象所属的类 class 信息中, 也会保存一个 epoch 值,每当遇到一个全局安全点时, 如果要对 class 进行批量再偏向, 则首先对 class 中保存的 epoch 进行增加操作, 得到一个新的 epoch_new
  • 然后扫描所有持有 class 实例的线程栈,根据线程栈的信息判断出该线程是否锁定了该对象, 仅将epoch_new 的值赋给被锁定的对象中。
  • 退出安全点后, 当有线程需要尝试获取偏向锁时, 直接检查 class中存储的 epoch 值是否与目标对象中存储的 epoch 值相等,如果不相等, 则说明该对象的偏向锁已经无效了, 可以尝试对此对象重新进行偏向操作。

整个锁升级过程

参考文章

偏向锁,轻量级锁与重量级锁的区别与膨胀

Java中的偏向锁,轻量级锁, 重量级锁解析

到此这篇关于Java锁升级的实现过程的文章就介绍到这了,更多相关Java锁升级内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java synchronized锁升级jol过程详解

    jol(java object layout)需要的依赖 <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.10</version> </dependency> 一.synchronized锁对象的升级(膨胀)过程主要如下: 1.膨胀过程:无锁(锁对象初始化时)-> 偏向

  • Java锁的升级策略 偏向锁 轻量级锁 重量级锁

    这三种锁是指锁的状态,并且是专门针对Synchronized关键字.JDK 1.6 为了减少"重量级锁"的性能消耗,引入了"偏向锁"和"轻量级锁",锁一共拥有4种状态:无锁状态.偏向锁.轻量级锁.重量级锁.锁状态是通过对象头的Mark Word来进行标记的: 锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁,这种锁升级却不能降级的策略,是为了提高获得锁和释放锁的效率 重量级锁:依赖于底层操作系统的Mutex Lock,线程会被阻

  • Java锁升级的实现过程

    对象内存布局 Java对象在内存中存储的布局可以分为3块区域: 对象头.实例数据.对齐填充. 对象头,分为两个部分,第一个部分存储对象自身的运行时数据,又称为Mark Word,32位虚拟机占32bit,64位虚拟机占64bit.如图所示,不同锁状态下,Mark Word的结构,理解下面要介绍的各种锁,和锁升级过程,都需要先充分了解Mark Word的结构. 第二部分是类型指针,指向类元数据指针,虚拟机通过此指针,确定该对象属于那个类的实例. 轻量级锁 轻量级锁是相对于重量级锁(Synchrno

  • Java Synchronized锁升级原理及过程剖析

    目录 前言 工具准备 对象的内存布局 锁升级过程 偏向锁 轻量级锁 重量级锁 总结 前言 在上篇文章深入学习Synchronized各种使用方法当中我们仔细介绍了在各种情况下该如何使用synchronized关键字.因为在我们写的程序当中可能会经常使用到synchronized关键字,因此JVM对synchronized做出了很多优化,而在本篇文章当中我们将仔细介绍JVM对synchronized的各种优化的细节. 工具准备 在正式谈synchronized的原理之前我们先谈一下自旋锁,因为在s

  • java锁升级过程过程详解

    目录 1.说到锁升级的过程,我们就得说一下对象头 对象头 对象头的存在形式 接下来让我们看看锁升级的过程 专业版解释 我通过马士兵老师讲的带味道的栗子大致懂了这个过程(菜鸟版理解) 总结 1.说到锁升级的过程,我们就得说一下对象头 对象头 java对象保存在内存中,由3个部分组成: 1. 对象头 2. 实例数据 3. 对齐填充字节 4. 如果是数组还包含数组长度 对象头的存在形式 让我们先看看图,主要来说一下 Mark Word markword 8bytes class pointer - 指

  • 关于Java锁性能提高(锁升级)机制的总结

    目录 Java锁性能提高机制 锁偏向 轻量级锁 自旋锁 重量级锁 Java锁升级简述 对象头结构 synchronized关键字 monitor 锁的四种状态 Java锁性能提高机制 锁的使用很难避免,如何尽量提高锁的性能就显得比较重要了 锁偏向 所谓的偏向锁是指在对象实例的Mark Word(说白了就是对象内存中的开头几个字节保留的信息,如果把一个对象序列化后明显可以看见开头的这些信息),为了在线程竞争不激烈的情况下,减少加锁及解锁的性能损耗(轻量级锁涉及多次CAS操作)在Mark Word中

  • JAVA对象分析之偏向锁、轻量级锁、重量级锁升级过程

    在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分: 对象头(Header) 实例数据(Instance Data) 对齐填充(Padding). 对象头 HotSpot虚拟机(后面没有说明的话默认是这个虚拟机)对象头包括三部分: Mark Word 指向类的指针 数组长度(只有数组对象才有) 对象头之Mark Word Mark Word记录了对象和锁有关的信息,当这个对象被synchronized关键字当成同步锁时,围绕这个锁的一系列操作都和Mark Word有关. Mar

  • 深入了解Java Synchronized锁升级过程

    目录 前言 对象结构 对象头 (1)无锁 (2)偏向锁 (3)轻量级锁 (4)重量级锁 对象体 对齐字节 锁升级 补充:Synchronized底层原理 EOF 前言 首先,synchronized 是什么?我们需要明确的给个定义——同步锁,没错,它就是把锁. 可以用来干嘛?锁,当然当然是用于线程间的同步,以及保护临界区内的资源.我们知道,锁是个非常笼统的概念,像生活中有指纹锁.密码锁等等多个种类,那 synchronized 代表的锁具体是把什么锁呢? 答案是—— Java 内置锁.在 Jav

  • Java中synchronized锁升级的过程

    目录 简介 CAS markWord Synchronized的锁升级 偏向锁 轻量级锁 重量级锁 总结 简介 在多线程中解决线程安全的问题时常用到Synchronized,现在的synchronized相对于早期的synchronized做出了优化,从以前的加锁就是重量级锁优化成了有一个锁升级的过程(偏向锁->轻量级锁->重量级锁). CAS cas的全称是compare and swap,从名称上可以看出它是先比较再进行设置,它是一种在多线程环境下实现同步功能的机制. 下面这段代码是在Re

  • 浅谈Java锁的膨胀过程以及一致性哈希对锁膨胀的影响

    目录 1.锁优化 1.1.锁消除 1.2.锁粗化 1.3.自旋锁 1.4.自适应自旋锁 1.5.锁膨胀 2.锁膨胀实战 2.1.jol工具 2.2.锁膨胀测试代码 2.3.输出分析 2.4.锁释放 3.一致性哈希对锁膨胀的影响 4.锁性能测试 1.锁优化 在JDK6之前,通过synchronized来实现同步效率是很低的,被synchronized包裹的代码块经过javac编译后,会在代码块前后加上monitorenter和monitorexit字节码指令,被synchronized修饰的方法则

随机推荐