精华内容
下载资源
问答
  • Synchronized锁升级

    2019-07-13 13:52:05
    Synchronized锁升级 锁的4中状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高) 为什么要引入偏向锁? 因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞争的,...

    Synchronized锁升级

     

    锁的4中状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高)

     

     

     

     

    为什么要引入偏向锁?

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

     

     

    为什么要引入轻量级锁?

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

     

    轻量级锁什么时候升级为重量级锁?

    自旋的时间太长也不行,因为自旋是要消耗CPU的,因此自旋的次数是有限制的,比如10次或者100次,如果自旋次数到了线程1还没有释放锁,或者线程1还在执行,线程2还在自旋等待,这时又有一个线程3过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。

     

    *注意:为了避免无用的自旋,轻量级锁一旦膨胀为重量级锁就不会再降级为轻量级锁了;偏向锁升级为轻量级锁也不能再降级为偏向锁。一句话就是锁可以升级不可以降级,但是偏向锁状态可以被重置为无锁状态。

     

    这几种锁的优缺点(偏向锁、轻量级锁、重量级锁)

     

    转自:kancy

    展开全文
  • synchronized锁升级

    2020-03-18 22:04:01
    synchronized锁升级 无锁->偏向锁 当一个对象刚实例化时,没有线程来访问它,这时这个对象是可偏向的。当第一个线程来访问它时,线程查看该对象的Mark Word(对象头里的数据结构)里是否有指向自己的线程id。这时...

    synchronized锁升级

    无锁->偏向锁

    当一个对象刚实例化时,没有线程来访问它,这时这个对象是可偏向的。当第一个线程来访问它时,线程查看该对象的Mark Word(对象头里的数据结构)里是否有指向自己的线程id。这时没有,线程会使用CAS操作修改Mark Word的状态为偏向锁并且将Mark Word的线程id指向自己。线程下一次来访问时,检查到有自己的id就可以直接使用了,使用偏向锁可以节省CAS时间。

    偏向锁->轻量级锁

    当第二个线程来访问时,也会检查有没有自己的线程id,也会去CAS操作尝试去修改Mark Word。等待锁指向的线程到达全局安全点,暂停锁指向的线程,查看线程是否还活着。如果挂了或者没有在使用该锁了,就可以将对象的线程id修改为指向自己(第二个线程)的线程id,这样仍然是偏向锁。如果还在使用锁,则偏向锁升级为轻量级锁,此时执行第一个线程,在栈桢中建立存储锁记录的空间,将Mark Word复制到这个空间,然后CAS操作将Mark Word替换为指向这个空间的指针。升级为轻量级锁后,第一个线程继续执行同步代码,第二线程进入自旋尝试获取锁。轻量级锁通过自旋来避免线程上下文切换的开销,但会占用CPU。
    当第一个线程执行完同步代码,将释放轻量级锁,通过CAS操作将栈桢中的Mark Word复制对象替换回对象头。操作成功则仍然是轻量级锁。

    轻量级锁->重量级锁

    当锁为轻量级锁时,自旋超过一定次数,或者出现一个线程占有锁,一个线程在自旋,还有第三个来访者时,锁升级为重量级锁(修改Mark Word为指向重量级锁的指针,这样轻量级锁的持有线程释放时的CAS操作就会失败),这时除了拥有锁的线程,其他竞争锁的线程阻塞,防止CPU空转。
    重量级锁通过对象的监视器(Monitor)实现,Monitor本质量依赖于操作系统的Mutex Lock实现。JVM基于进入和退出Monitor对象来实现同步。

    展开全文
  • synchronized 锁升级

    2020-07-16 13:43:19
    synchronized (this){ //todo } 当执行同步代码块时,会创建记录对象,每个线程的栈帧中包含一个记录的结构, 记录中Object reference指向对象,并尝试用cas替换Object的mark word,将mark word的值...

    一、轻量级锁

    如果一个对象有多个线程访问,但是多线程访问的时间是错开的(没有竞争),那么可以使用轻量级锁来优化。

    synchronized (this){
        //todo
    }

    当执行同步代码块时,会创建锁记录对象,每个线程的栈帧中包含一个锁记录的结构,

    锁记录中Object reference指向锁对象,并尝试用cas替换Object的mark word,将mark word的值存入所记录。

    1、加锁

    (1)如果cas成功,对象头中存储了锁记录地址和状态00,表示由该线程给对象加锁。

    (2)cas失败

    i)如果其他线程已经持有了该Object的轻量级锁,表明出现竞争,进入锁膨胀。

    ii)如果是自己执行锁重入,那么再添加一条锁记录作为重入的计数

    2、解锁

    (1)当退出同步代码块时,如果有锁记录的值为null,则表明出现了重入,这时重置锁记录

    (2)当退出同步代码块时,如果锁记录的值不为null,这时使用cas将mark word的值恢复给对象头。

             cas成功,则解锁成功,cas失败,说明轻量级锁进行了锁膨胀或者升级为重量级锁,此时需要进入重量级锁解锁过程。

    二、锁膨胀

    当thread-1进行轻量级加锁,但是Thread-0已经对该对象加了轻量级锁。

    Thread-1加轻量级锁失败,进入锁膨胀流程

    (1)为锁对象申请重量级(Monitor)锁,让对象指向重量级锁。

    (2)Thread-1自己进入Monitor的EntryList 阻塞队列中。

    注意:

    Thread-0在退出同步代码块时,使用cas将mark word的值恢复给对象头失败了,这时会进入重量级解锁流程,即找到Monitor对象,设置Monitor对象的Owner为null,唤醒EntryList中的阻塞线程。

    三、重量级锁之自旋优化(最好在多核下有效果)

    重量级锁在竞争中的时候,还可以使用自旋来进行优化,如果当前线程自旋成功,此时当前线程避免进入阻塞。

    在jdk6之前,自旋是自适应的,比如,对象刚刚有过一次自旋操作成功过,那么认为这次自旋成功的可能性会高,就会多自旋几次,反之会少自旋几次。

    四、偏向锁

    轻量级锁在无竞争时,每次都需要cas操作,jdk6引入了偏向锁来做进一步的优化

    第一次使用cas将线程id设置到对象头的mark word头上,之后在加锁发现这个线程id是自己的,则认为没有竞争,不使用cas。

    一个对象创建时,偏向锁是默认开启的,对象的mark word的后3位为101,这时thread,epoch,age都为0

    偏向锁默认是延迟的,不会在程序启动时立即生效,如果避免延迟可以加jvm参数:-XX:BiasedLockingStartupDelay=0来禁用延迟。

    如果没有开启偏向锁,那么对象创建后,markword的值的最后3位001,hashcode,age都为0,第一次使用hashcode时才会赋值。

    偏向锁的撤销

    (1)调用锁对象的hashcode,会禁用偏向锁,原因是hashcode占用31位,在偏向状态下无法存入,只能撤销偏向状态。

    轻量级锁下,调用hashcode不会导致轻量级状态失效,因为hashcode保存在栈帧的所记录里,等到解锁时会再次赋值到marword里。

    同理重量级锁调用hashcode,也不会导致重量级状态失效,因为hashcode保存在monitor的对象里,解锁后,会被重置到锁对象的mark word里。

    (2)当有其他线程使用偏向锁对象时,会将偏向锁对象状态撤销,同时锁升级为轻量级锁。

    (3)调用wait和notify会导致偏向锁失效,同时锁升级为重量级锁,因为wait和notify只有重量级锁有。

    五、批量偏向锁

    如果对象虽然被多个线程访问,但是没有竞争,这时偏向对象的线程id有机会重新偏向给线程id2,jvm对这种线程之间偏向锁的撤销做了优化,即当偏向锁阈值超过20次后,jvm会将这些偏向锁对象的线程id重新赋值为当前线程id。

    当撤销偏向锁阈值超过40次后,jvm会禁用偏向锁,即会出现所膨胀。

     

     

     

    展开全文
  • Synchronized 锁升级

    2019-05-11 21:54:24
    Synchronized是JAVA的一种形式,是基于JVM层面进行实现。主要有两种用法 修饰方法 在实现时,class文件有特殊标识符ACC_SYNCHRONIZED...在jdk6之后Synchrozied 升级了,具有多种的形式,偏向,轻量级,自...

    Synchronized是JAVA锁的一种形式,是基于JVM层面进行实现。主要有两种用法

    • 修饰方法
      • 在实现时,class文件有特殊标识符ACC_SYNCHRONIZED作用于同步方法
    • 修饰代码块
      • 在实现时,class文件会有两条指令monitorenter及monitorexit,作用于代码块之间

    在jdk6之后Synchrozied 升级了,具有多种锁的形式,偏向锁,轻量级锁,自旋锁,及重量级锁。这几种锁之间是只升不降。

    即偏向锁可以升级为轻量级锁,但是轻量级锁不能降低为偏向锁。接下来我们来看看锁是怎么升级的。

    首先来看看一个作用于Synchronized对象是怎么表示"被获得锁的",主要是用对象头的32个字节来标识的。接下来我们借用一张图,来看看对象头。

    当锁处于不同时期的时候,这32个字节所存在的内容也是不一样的。

    当一个线程要获得锁的时候,是从偏向锁开始的。首先判断该对象头是否处于无锁状态或者偏向锁状态,如果是则利用CAS操作将对象头的线程ID替换为当前ID,如果CAS操作成功,则代表获得偏向锁。如果失败则证明当前偏向锁被其他线程获得,需要注意的是偏向锁并不会主动释放,所以我们先看看获得该锁的线程是否存活,如果死了,就想锁置为无锁状态或者指向当前线程,如果线程存活,我们就去该线程的栈中看看锁记录是否还需要占用当前锁(这一步是我认为的),如果不占用,那还是置为无锁状态或者指向当前线程。如果占用,jvm 会再安全点释放偏向锁,并升级为轻量级锁。

    当线程获得轻量级锁时,首先会将对象头的markword字段复制到本线程的栈帧的锁记录空间中,并利用cas操作将原markword改为锁记录空间的指针,当线程2通过cas操作失败时,则先自旋一段时间。若通过多次自旋依然失败,则锁升级为重量级锁。

    至于重量级锁,我觉得就是类似于AQS的双向队列,有一个监视器,他有一个队列,保存需要该锁的线程。

    从偏向锁,轻量级锁,自选旋,到重量级锁。其实是锁不断升级优化的过程。偏向锁适用于大部份时间只有一个线程的场景,其消耗最小。

    有一点题外话记录一下:synchronized是确保了在获取锁和释放锁的时候都有内存屏障,且数据一定会从主内存中重新load或者store到主内存。

    展开全文
  • synchronized锁我们都知道在jdk 1.5时,synchronized锁是一个重量级锁,缺点如下:每次获取和释放锁都会带来用户态和内核态的切换,从而增加系统的性能开销 在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕在...
  • 1Mutex介绍Mutex中文名称是互斥,跟着中文名称很好理解了,就是为了互斥;在并发的情况下,对于一个对象的操作,可能会导致数据不...2经典问题引入前言:synchronized是获取对象!!!是一个操作,将对象加到代...
  • 这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作。一、锁有哪些分类一般我们提到的锁有以下这些:...
  • 对象头与monitorMarkWord区是存在在JAVA对象头中的一个...信息2.GC信息3.HashCode(如果有调用)public class Demo1 { public static void main(String[] args) throws IOException { Object o = new Object(); S...
  • 目录:锁的分类及其解释无锁偏向锁轻量级锁重量级锁锁优化自旋锁锁消除锁粗化锁的分类及其解释锁的4中状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高)锁升级是不可逆的(重要)先来个大体的流程...
  • synchronized锁升级过程

    2021-01-23 20:39:57
    synchronized锁升级过程为什么要进行锁升级锁升级预备知识之对象头锁升级预备知识之CASABA问题锁升级详细过程 为什么要进行锁升级 锁升级其实就是对synchronized的优化,以前用synchronized修饰一个对象或者是方法,...
  • 作者:求知人zzzliu链接:https://www.jianshu.com/p/a48801624fe9java对象头由3部分组成:1、Mark Word2、指向类...一、偏向1、概念:HotSpot的作者经过研究发现,大多数情况下,不仅不存在多线程竞争,而且总...
  • 主要介绍了Java synchronized锁升级jol过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Synchronized锁升级过程

    2021-05-05 16:32:26
    Synchronized锁升级过程 锁在jdk1.6之前只有两种状态:无锁和有锁两种状态,在jdk1.6之后,对synchronized进行了优化,增加了两种状态,现在锁一共有四种状态:无锁、偏向锁、轻量级锁、重量级锁。 无锁也是一种状态...
  • synchronized 锁升级过程

    2020-07-24 16:33:35
    synchronized 锁升级过程就是其优化的核心:偏向锁->轻量级锁->重量级锁 class Test{ private static final Object object = new Object(); public void test(){ synchronized(object) { // do ...
  • synchronized锁升级详解

    2020-02-09 14:20:47
    synchronized锁升级 在JDK1.5之前,我们要想实现线程同步,只能通过synchronized关键字这一种方式达成。synchronized关键字是JVM实现的一种内置锁。从底层角度来说,这种锁释放和获取都是jVM帮我们隐式实现的。 从...
  • synchronized锁升级[1] Java对象头[2] Mark word 结构[3] Monitor[4] synchronized锁升级无锁偏向锁(可关闭)轻量级锁重量级锁[5] synchronized锁流程[6] synchronized锁对比 [1] Java对象头 我们以 Hotspot 虚拟机...
  • 首先说明一下,锁升级和锁降级说的根本不是一个事情,锁升级是...之前介绍过synchronized关键字,synchronized关键字可以锁类,锁方法和锁代码块,有关synchronized关键字的使用可以参考链接2,synchronized锁...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,554
精华内容 621
关键字:

synchronized锁升级