轻量级锁原理

简介

轻量级锁又叫自旋锁,在用户态完成操作,没有涉及操作系统底层


示例代码

/**
 * @author pangjian
 * @ClassName LightWeightLocking
 * @Description 轻量级锁加锁解锁过程示例代码
 * @date 2021/11/1 10:55
 */

public class LightWeightLocking {

    static final Object obj = new Object();

    public static void main(String[] args) {
        synchronized (obj) {
            method();
        }
    }

    public static void method() {
        synchronized (obj) {
            System.out.println("++++");
        }
    }

}

原理

加锁成功原理

  • 当Thead-0执行到主方法的synchronized(obj)就会在栈帧中生成lock record(锁记录),内部可以存储锁定对象的mark word

在这里插入图片描述

  • 让锁记录中Object reference指向锁对象,并尝试CAS替换Object的markword,将markword的值存入锁记录(暂存效果,解锁后还会把原来的hashcode,age信息替换回给Object)

在这里插入图片描述

  • 如果CAS替换成功,Object的markword中存储了锁记录地址和状态00,表示由该线程给对象加上了锁

在这里插入图片描述

CAS失败和解锁原理

  • 如果是其它线程已经持有了该Object的轻量级锁,这时表明有竞争,进入锁自旋过程
  • 如果是自己执行了synchronized锁重入,那么再添加一条Lock Record作为重入的计数

在这里插入图片描述

当退出synchronized 代码块(解锁时)如果有取值为nul的锁记录,表示有重入,这时重置锁记录,表示重入计数减一,当退出synchronized代码块(解锁时)锁记录的值不为null,这时使用CAS将Mark Word 的值恢复给对象头,成功则解锁成功。也可能失败,就是因为其他线程也要对该Object对象进行CAS失败后导致锁自旋了(也就是说自旋锁),自旋失败后锁膨胀了,变成了重量级锁。

在这里插入图片描述


自旋和锁膨胀

如果在尝试加轻量级锁的过程中,CAS操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有竞争),这时当前线程就会自旋(其实就是循环进行CAS操作),如果线程自旋到一定阈值或自旋线程数超cpu核心数的一定比例就会导致锁膨胀,将轻量级锁变为重量级锁。

在这里插入图片描述

  • 线程1CAS加锁失败,进入锁自旋流程
  • 自旋失败(有线程超过十次自旋或自旋线程数超过cpu核心数的一半)后为Object对象在操作系统中申请Monitor锁(lock record 地址 00 变成了monitor 地址 10),并让Object指向重量级锁地址
  • 线程1进入monitor的EntryList(等待队列)

在这里插入图片描述

  • 当Thread-O退出同步块解锁时,使用CAS将Mark Word的值恢复给对象头,失败。这时会进入重量级解锁流程,即按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中 BLOCKED线程

和重量级锁比较

如果临界区代码执行时间长,也就是同步代码量大和等待线程数大,就需要用重量级锁(悲观锁),因为转圈算法(轻量级锁)要占用cpu时间片,如果等待线程数多也会耗费大量资源,如果用排队算法(重量级锁),就不要cpu分配时间片

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值