轻量级锁的加锁、释放锁以及相关知识

  • 什么时候会升级为轻量级锁?
    当关闭偏向锁功能,对象处于已偏向已锁定、已偏向未锁定但不支持重偏向的场景下或多个线程竞争偏向锁导致偏向锁升级为轻量级锁,会尝试获取轻量级锁
  • 加锁过程:
    判断对象是不是无锁状态(第三位=001),如果是,执行1,否则执行3。
    1.线程在执行同步代码块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间——Lock Record。并将对象头中的Mark Word复制到锁记录中的displaced_header 属性中,这个被复制过来的记录叫做Displaced Mark Word,将Owner指向当前对象。
    2.然后线程尝试使用CAS将锁对象对象头中的Mark Word替换为指向锁记录的指针,
    如果CAS替换成功,则当前线程获得轻量级锁,替换成功后,需要修改原对象头Mark Word中的锁状态标志位为00,目的是告诉其它线程此对象已经被轻量级锁锁定。
    3.如果CAS替换失败,A.当对象处于轻量级锁状态时,会去检验Mark Word是否指向当前线程的栈帧,
    如果是:则这次是锁重入,要新创建一个锁记录,将该锁记录中的Displaced Mark Word设置为null,并将Owner指向当前对象,起到了一个重入计数器的作用。(之后的锁重入都会在线程栈中分配一个Displaced Mark word为null的Lock Record,以此表示锁重入的次数)
    如果不是:该线程获取轻量级锁失败,未获取到轻量级锁的该线程将锁膨胀为重量级锁,持有轻量级锁的对象头的Mark Word改为指向重量级锁monitor的指针。 获取失败的线程不会立即阻塞,会先适应性自旋,尝试获取锁。到达临界值后自旋失败,该线程进入Monitor的EntryList等待队列中,直到被唤醒(锁持有者释放锁)。

    适应性自旋:自旋的时间(次数)不再固定,由前一次在同一个锁上的自旋时间以及锁的拥有者的状态决定。
    A:如果在同一个锁对象上,刚刚有自选等待获得过锁的,并且持有锁的线程正在运行中,那么JVM认为此次自旋很可能会再次成功,则允许其自选等待持续更长的时间。
    B:如果很少成功获得该锁,可能会之间省略自选过程,之间阻塞线程,避免浪费处理器资源。
     


    解锁过程:
    轻量级锁加锁时有锁重入的可能,同样的,在解锁时也需要判断是否是锁重入解锁。

    code 1 :检索当前线程栈中的锁记录空间,从低位往高位找到第一条和此对象有关的Lock Record。加锁时,如果是锁重入,会将锁记录的 Displaced Mark Word 设置为 null,相应的,在解锁时需要判断Displaced Mark Word是否为 null,如果是,则说明是锁重入解锁,移除onwer的指向,不做替换操作;如果不是,执行code 2。

    code 2:通过CAS把当前线程栈帧Lock Record中的Displaced Mark Word替换到对象头的Mark Word中去,如果替换成功,则轻量级解锁成功;
    如果替换失败,则说明发生了锁膨胀,对象现在是重量级锁定状态,执行code 3。(轻量级锁未释放前被其它线程尝试获取,此时Mark Word指针已经被替换为指向Monitor,所以释放锁时CAS会失败,此时需要走重量级解锁流程。)

    code 3:执行重量级锁释放流程,释放重量级锁,同时唤醒被阻塞的线程去获取锁。
     
  • 什么时候会升级为重量级锁?
    当竞争产生时就会升级为重量级锁,比如,两个线程同时获取锁,成功的线程会获取到轻量级锁,失败的线程首先会进行适应性自旋,如果在自旋的过程中获取到了锁,则不会进行锁升级,如果到达了适应性自旋的次数仍然没有成功获取到锁(其次数由上一次获取该锁的时间以及持有锁线程的情况而定),会执行锁膨胀,将锁升级为重量级锁。
     
  • 轻量级锁如何实现锁重入?
    当轻量级锁已经被线程持有,且对象头的Mark Word指向的是当前线程的栈帧时,会把本条Lock Record的Displaced Mark Word 设置为 null,实现锁重入。之后的锁重入都会在线程栈中分配一个Displaced Mark word为null的Lock Record,以此表示锁重入的次数
     
  • 轻量级锁是否会自旋?
    轻量级锁流程不会自旋,自旋发生在产生竞争后,获取失败的线程才会进行自旋。失败的线程不会立刻阻塞,而是先尝试适应性自旋,自旋的线程在自旋过程中,如果成功获得资源(即之前获的资源的线程执行完成并释放了共享资源),则整个状态依然处于轻量级锁的状态,如果自旋失败(到了临界值),则将锁膨胀为重量级锁,自己进入重量级锁的阻塞队列中,等待持有锁的线程释放锁后对其唤醒。

    以上是为了让自己复习时阅读的更加顺畅所写的笔记,有错误请指出,谢谢

     
  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值