精华内容
下载资源
问答
  • 主要介绍了Java synchronized锁升级jol过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Java锁升级的实现过程

    2020-08-19 04:53:59
    主要介绍了Java锁升级的实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • java锁升级过程

    万次阅读 多人点赞 2020-03-14 20:32:17
    java中对象有4种状态:(级别从低到高) 1.无锁状态 2.偏向状态 3.轻量级状态 4.重量级状态 对象头分两部分信息,第一部分用于存储哈希码、GC分代年龄等,这部分数据被称为"Mark Word"。在32位的HotSpot...

    java中对象锁有4种状态:(级别从低到高)
    1.无锁状态
    2.偏向锁状态
    3.轻量级锁状态
    4.重量级锁状态

    对象头分两部分信息,第一部分用于存储哈希码、GC分代年龄等,这部分数据被称为"Mark Word"。在32位的HotSpot虚拟机中对象未被锁定的状态下,Mark Word的32bit空间中的25bit用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0,在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容见下表:
    在这里插入图片描述
    锁升级的方向是:无锁——>偏向锁——>轻量级锁——>重量级锁,并且膨胀方向不可逆。

    1.偏向锁
    偏向锁是JDK6中引入的一项锁优化,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。
    偏向锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要同步。

    2.轻量级锁
    如果明显存在其它线程申请锁,那么偏向锁将很快升级为轻量级锁。

    3.自旋锁
    自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

    4.重量级锁
    指的是原始的Synchronized的实现,重量级锁的特点:其他线程试图获取锁时,都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程。

    锁升级场景:

    场景1: 程序不会有锁的竞争。
    那么这种情况我们不需要加锁,所以这种情况下对象锁状态为无锁。

    场景2: 经常只有某一个线程来加锁。
    加锁过程:也许获取锁的经常为同一个线程,这种情况下为了避免加锁造成的性能开销,所以并不会加实际意义上的锁,偏向锁的执行流程如下:
    1、线程首先检查该对象头的线程ID是否为当前线程;
    2、A:如果对象头的线程ID和当前线程ID一直,则直接执行代码;B:如果不是当前线程ID则使用CAS方式替换对象头中的线程ID,如果使用CAS替换不成功则说明有线程正在执行,存在锁的竞争,这时需要撤销偏向锁,升级为轻量级锁。
    3、如果CAS替换成功,则把对象头的线程ID改为自己的线程ID,然后执行代码。
    4、执行代码完成之后释放锁,把对象头的线程ID修改为空。

    场景3: 有线程来参与锁的竞争,但是获取锁的冲突时间很短。
    当开始有锁的冲突了,那么偏向锁就会升级到轻量级锁;线程获取锁出现冲突时,线程必须做出决定是继续在这里等,还是回家等别人打电话通知,而轻量级锁的路基就是采用继续在这里等的方式,当发现有锁冲突,线程首先会使用自旋的方式循环在这里获取锁,因为使用自旋的方式非常消耗CPU,当一定时间内通过自旋的方式无法获取到锁的话,那么锁就开始升级为重量级锁了。

    场景4: 有大量的线程参与锁的竞争,冲突性很高。
    我们知道当获取锁冲突多,时间越长的时候,我们的线程肯定无法继续在这里死等了,所以只好先休息,然后等前面获取锁的线程释放了锁之后再开启下一轮的锁竞争,而这种形式就是我们的重量级锁。

    展开全文
  • Java锁升级

    千次阅读 多人点赞 2020-04-06 01:36:52
    Java锁升级 对象内存布局 Java对象在内存中存储的布局可以分为3块区域: 对象头、实例数据、对齐填充。 对象头,分为两个部分,第一个部分存储对象自身的运行时数据,又称为Mark Word,32位虚拟机占32bit,64位虚拟机占...

    Java锁

    锁概念

    公平锁与非公平锁

    公平锁:线程获取锁的顺序与其申请顺序一致

    非公平锁:线程获取锁的顺序并不是按照申请锁顺序,有可能后申请锁的线程先获取锁。

    可重入锁与不可重入锁

    可重入锁:线程获取锁后,可以重复进入同步代码区,不需要重复申请锁

    不可重入锁:线程每次进入同步代码区时,均需要获取锁,即使已经获取过该锁。

    悲观锁与乐观锁

    悲观锁:总是持有悲观的态度,认为并发冲突一般会发生

    乐观锁:总是持有乐观的态度,认为并发冲突一般不会发生

    锁消除与锁粗化

    锁消除:消除是Java虚拟机在JIT编译期间,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过锁消除,可以节省毫无意义的请求锁时间。

    锁粗化:在遇到一连串地对同一锁不断进行请求和释放的操作时,把所有的锁操作整合成对锁的一次请求,从而减少对锁的请求同步次数

    自旋锁和自适应自旋

    自旋锁:线程尝试获取锁,发现被占用后,不放弃cpu执行时间,进入阻塞状态,而是进入进行循环重试,重试指定次数后,仍未获取锁,则进入阻塞过程。

    自适应自旋:重试次数不固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

    Java锁升级

    对象内存布局

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

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

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

    偏向锁

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

    • 偏向锁的获取

      开启偏向锁模式后,锁第一次被线程获取的时候,虚拟机会把对象头中是否为偏向锁的标志位设位1,

      同时使用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 值相等,如果不相等, 则说明该对象的偏向锁已经无效了, 可以尝试对此对象重新进行偏向操作。

    轻量级锁

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

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

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

      • 如果只有一个线程尝试获取轻量级锁,会进行自旋等待,一旦有两条以及以上的线程抢占该锁,轻量级锁会升级为重量级锁。

        锁标志位置为10,Mark Word存储的就是指向重量级锁的指针

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

    整个锁升级过程

    参考文章

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

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

    展开全文
  • Java 锁升级(锁膨胀)、锁降级

    千次阅读 2020-09-10 11:22:13
    锁升级:偏向锁、轻量级锁、重量级锁的过渡。 https://blog.csdn.net/haoranhaoshi/article/details/92388612 优先尝试低级锁,不能适用,就升级锁。线程获取到不被其他线程获取的监视类或对象,监视类或对象头部...

    锁升级:偏向锁、轻量级锁、重量级锁的过渡。

    https://blog.csdn.net/haoranhaoshi/article/details/92388612

    优先尝试低级锁,不能适用,就升级锁。线程获取到不被其他线程获取的监视类或对象,监视类或对象头部记录线程ID,线程退出对监视类或对象的获取时直接退出,是偏向锁。如果有其他线程来获取监视类或对象,发现头部记录的线程ID不是自己的ID(https://blog.csdn.net/haoranhaoshi/article/details/108501633),就升级为轻量级锁。轻量级锁采用CAS机制(https://blog.csdn.net/haoranhaoshi/article/details/108507092),尝试一定次数(默认10)获取不到监视类或对象,则升级为重量级锁(一旦获取不到监视类或对象就阻塞(https://blog.csdn.net/haoranhaoshi/article/details/108461058))。

    因为操作唤醒阻塞的线程需从用户态切换到内存态,开销大,所以才优先使用轻量级锁进行循环判断是否可获取监视类或对象。

    锁降级:写锁降级成为读锁。持有写锁的同时,获取到读锁,然后释放写锁。避免读到被其他线程修改的数据。

    oracle官网锁降级示例:

     class CachedData {
       Object data;
       volatile boolean cacheValid;
       final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    
       void processCachedData() {
         rwl.readLock().lock();
         // 缓存无效
         if (!cacheValid) {
            // Must release read lock before acquiring write lock
            // 释放读锁
            rwl.readLock().unlock();
            // 尝试获取写锁
            rwl.writeLock().lock();
            try {
              // Recheck state because another thread might have
              // acquired write lock and changed state before we did.
              // 再次判断获取是否无效
              if (!cacheValid) {
                  // 获取数据
                data = ...
                cacheValid = true;
              }
              // Downgrade by acquiring read lock before releasing write lock
              // 锁降级
              rwl.readLock().lock();
            } finally {
              rwl.writeLock().unlock(); // Unlock write, still hold read
            }
         }
         // 经过很长的时间做一些处理、而且不想我刚刚自己更新的数据被别人改了
         try {
           use(data);
         } finally {
           rwl.readLock().unlock();
         }
       }
     }

     

    展开全文
  • Java锁升级过程

    2020-09-11 15:49:12
    Java锁升级过程Java对象头二、锁种类三、具体过程 Java对象头 synchronized用的锁存在Java对象头里,Java对象头里的Mark Word默认存储对象的HashCode、分代年龄和锁标记位。在运行期间,Mark Word里存储的数据会随着...

    一、Java对象头

    synchronized用的锁存在Java对象头里,Java对象头里的Mark Word默认存储对象的HashCode、分代年龄和锁标记位。在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。32位JVM的Mark Word可能变化存储为以下5种数据:
    在这里插入图片描述
    锁一共有四种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态随着竞争情况逐渐升级。为了提高获得锁和释放锁的效率,锁可以升级但不能降级,意味着偏向锁升级为轻量级锁后不能降级为偏向锁

    二、锁种类

    • 偏向锁
      因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞争的,常常是一个线程多次获得同一个锁,因此如果每次都要竞争锁会增大很多没有必要付出的代价,为了降低获取锁的代价,才引入的偏向锁。

    • 轻量级锁
      轻量级锁考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景。因为阻塞线程需要CPU从用户态转到内核态,代价较大,如果刚刚阻塞不久这个锁就被释放了,那这个代价就有点得不偿失了,因此这个时候就干脆不阻塞这个线程,让它自旋这等待锁释放。

    • 自旋锁
      减少线程上下文切换,提高执行效率

    • 重量级锁
      除拥有锁的线程外阻塞所有竞争线程

    三、具体过程

    线程A在进入同步代码块前,先检查MarkWord中的线程ID是否与当前线程ID一致,如果一致(还是线程A获取锁对象),则无需使用CAS来加锁、解锁。

    如果不一致,再检查是否为偏向锁,如果不是,则自旋等待锁释放。

    如果是,再检查该线程是否存在(偏向锁不会主动释放锁),如果不在,则设置线程ID为线程A的ID,此时依然是偏向锁。

    如果还在,则暂停该线程,同时将锁标志位设置为00即轻量级锁(将MarkWord复制到该线程的栈帧中并将MarkWord设置为栈帧中锁记录)。线程A自旋等待锁释放。

    如果自旋次数到了该线程还没有释放锁,或者该线程还在执行,线程A还在自旋等待,这时又有一个线程B过来竞争这个锁对象那么这个时候轻量级锁就会膨胀为重量级锁。 重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。

    如果该线程释放锁,则会唤醒所有阻塞线程,重新竞争锁。
    在这里插入图片描述

    展开全文
  • Java锁原理 在探究Java锁原理之前我们需要知道一些基础知识,方便对锁的理解: synchronized关键字 CAS Java对象内存模型 CAS CAS概述 CAS(Compare And Swap)比较和替换 定义一个int类型的变量a,初始值为0。 ...
  • 隐式(内置) - synchronized的使用方法: 1.synchronized 加在方法上面,是加在当前类的对象上面,this。 2.synchronized 加在静态方法上面,加在当前方法所在类的上面Test.class. 3.synchron
  • JDK1.6为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”,所以在JDK1.6里锁一共有四种状态,无锁状态,偏向锁状态,...锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。
  • Java锁性能提高(锁升级)机制总结

    千次阅读 多人点赞 2017-03-21 11:38:37
    的使用很难避免,如何尽量提高的性能就显得比较重要了 偏向 所谓的偏向是指在对象实例的Mark Word(说白了就是对象内存中的开头几个字节保留的信息,如果把一个对象序列化后明显可以看见开头的这些信息)...
  • 锁升级顺序 偏向锁 轻量级锁 自旋锁 重量级锁 偏向锁 如果一个线程获得了锁,再次请求的时候就不需要再去获取锁。如果发现有其他线程来获取这个锁,就升级为轻量级锁。 理论基础: 在大多数情况下,锁不仅不存在多...
  • Java对象的锁升级过程 在JDK1.7版本之后,对Sunchronized关键字进行了优化,如果对对象进行Synchronized进行加锁,那么针对资源的竞争情况不同,锁会有一个升级的过程,以保证资源是最佳的利用状况。 过程可以概括为...
  • 1、锁升级 2、锁粗化 3、锁消除 一、Synchronized使用场景 Synchronized是一个同步关键字,在某些多线程场景下,如果不进行同步会导致数据不安全,而Synchronized关键字就是用于代码同步。什么情况下会数据不...
  • Java中锁的四种状态以及锁升级过程

    千次阅读 2020-11-11 23:11:10
    Java(1.6+)中的状态一共有四种,级别由低到高分别是:无锁、偏向、轻量级、重量级,这几个状态会随着竞争情况逐渐升级,其中可以升级,但是不能降级。Java中加的最简单方式就是加synchronized关键字...
  • 在本文中小编给的大家整理了关于Java锁升级策略 偏向锁 轻量级锁 重量级锁的相关知识点内容,需要的朋友们参考下。
  • 面试必备java synchronized升级

    千次阅读 2020-03-16 23:35:39
    首先祭出下图,上图是线程获取锁和锁升级的基本流程(来自 这里 1 了解 synchronized synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的。是Java内置的机制,是JVM层面的。 jdk 1.6以前synchronized ...
  • 读写支持降级: 获取写,获取读,释放写,释放读 降级可解决单线程下写读不一致的场景,即写i=1,后读出来i=2。虽然没有什么大问题,但是不满足单线程下的as-if-serial语义,即按照程序编写的顺序,...
  • JDK1.6的优化 曾经遇到多线程加锁操作都是直接用synchronized,但在jdk1.6前,synchronized是重量级,随着jdk1.6对synchronized进行的各种优化后,synchronized并不会显得那么重 如: 偏向:偏向某一个线程...
  • Java synchronized锁升级过程简述(面试可用)

    千次阅读 热门讨论 2021-04-30 09:45:53
    java 锁升级流程 Synchronized 的锁升级流程是这样:无锁 ----> 偏向锁 ----> 轻量级 锁 ----> 锁自旋 ----> 重量级锁 偏向锁 偏向锁,简单的讲,就是在锁对象的对象头中有个ThreaddId字段,这个...
  • java中的升级过程

    2020-12-02 23:02:19
    java中的大概有3中,重量级,轻量级和偏向 现在来说一下他们的区别: 什么是重量级? 要搞清楚重量级,首先你要知道java 的内存模型。 jdk1.8 后 java使用的是HotSopt 内存模型。当你在启动一个线程的...
  • java并发之升级

    万次阅读 2018-06-19 19:49:34
    说明:本文大部分内容来自《并发编程的艺术》,再加上自己网络整理和理解 以下内容来自《java并发编程的艺术》作者:方鹏飞 魏鹏 程晓明 ...升级与对比 Java SE 1.6为了减少获得和释放...
  • java同步以及级别升级的理解

    千次阅读 2018-07-31 19:48:20
    首先简单说下先偏向、轻量级、重量级三者各自的应用场景: 偏向:只有一个线程进入临界区; 轻量级:多个线程交替进入临界区; 重量级:多个线程同时进入临界区。 还要明确的是,偏向、轻量级都...
  • 每个对象都有Monitor(监视器),当monitor被占用的时候,对象进入锁定状态。 monitorenter:线程通过monitorenter指令尝试获取monitor所有权,情况如下: 1、如果monitor的进入数为0,则该线程进入,进入数设置...
  • Java中的锁升级

    2020-07-23 23:52:42
    锁升级过程 Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这...
  • synchronized实现原理及锁升级过程

    千次阅读 2019-08-11 14:01:19
    synchronized实现原理及锁升级过程 前言: synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchronized已经变得原来...
  • Synchronized详细介绍之锁升级过程

    千次阅读 2020-09-24 15:07:15
    Synchronized详细介绍之锁升级过程前言线程与进程的区别进程线程区别协程二级目录三级目录 前言 我们在并发编程过程中,会有一些资源或者操作是必须要进行序列化访问的,就是线程之间不能并发的访问,必须要进行串行...
  • compare and swap 或者是compare and exchange ,就是用不上锁的方式来保证数据一致,实现多线程间的同步,java中的锁升级都是用CAS的方式,包括ActoicInteger等类,底层都是使用CAS,CAS就是读入一个变量,然后...
  • Java对象的内存分布Java多线程升级原理

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 63,438
精华内容 25,375
关键字:

java锁升级

java 订阅