轻量级锁和重量级锁-多线程安全-并发编程(Java)

1、轻量级锁

1.1、加锁

  • 使用场景:如果一个对象虽然有多个线程访问,但是多线程访问时间是错开的,即多线程之间不会发生竞争。
  • 轻量级锁对使用者是透明的,即语法仍然是synchronized

如下代码,2个同步方法,利用同一个对象加锁:

static final Object obj = new Object();
public static void method1() {
	synchronized(obj) {
		// 同步方法A
	}
}
public static void method2() {
	synchronized(obj) {
		// 同步方法B
	}
}

轻量级锁加锁过程解析:

  • 线程和对象的初始状态,图示:在这里插入图片描述

  • 创建锁记录(Lock Record)对象,每一个线程的栈帧都会包含一个锁记录的结构,内部用来存储锁对象的Mark Word 以及锁对象的地址。

  • 当线程Thread-0执行到synchronized同步代码块的时,把锁记录中Object Reference(指针)执行锁对象,并尝试用cas替换Object 的MarkWord,把MarkWord的值存入锁记录,图示:在这里插入图片描述

    • cas简单理解为原子操作,执行过程中不会被打断
    • 轻量级锁MardWord结构:ptr_to_lock_record:30 00
  • 如果cas替换成功,对象头中存储了锁记录地址和状态 00,表示由该线程加锁,图示:在这里插入图片描述

  • cas替换失败有两种情况

    • 如果有其他线程早于当前线程成功加锁,即Object MarkWord后2位一置为00,此时发生锁膨胀,升级为重量级锁
    • 如果是自己执行了synchronized锁重入,那么在添加一条Lock Record做为重入的计数,图示:在这里插入图片描述

1.2、解锁

解锁过程分析:

  • 当线程退出syncronized代码块时,如果有取值为null的锁记录,表示由重入,这时重置锁记录,表示重入此时减一
  • 当线程退出syncronized代码块时,如果锁记录的值不为null,这时使用cas把MarkWord的值恢复为最初的值(即保存在锁记录中的值)
    • 解锁成功
    • 解锁失败,说明轻量级锁进行了锁膨胀或者已经升级为重量级锁,进入重量级锁解锁过程。

2、重量级锁

2.1、加锁和解锁

如果在尝试加轻量级锁的过程中,CAS操作无法成功,其中一种情况就是有其他线程给该对象已经加上轻量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。

  • 当Thread-1进行轻量级锁加锁时,Thread-0已经给该对象加了轻量级锁。

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

    • 即为Object 对象申请Monitor锁,让Object指向Monitor地址
    • 然后自己进入Monitor的EntryList Blocked
    • 图示,在这里插入图片描述
  • 解锁:当Thread-0退出同步块解锁时,使用cas将MarkWord的值恢复给对象头,失败。这时,会进入重量级解锁流程,即按照Monitor地址找到Monitor对象,设置Owner值为null,唤醒EntryList中阻塞的线程。

2.2、自旋优化

重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即持锁线程已经退出同步块,释放了锁),这是当前线程就可以避免阻塞。

自旋成功的情况

线程1(cup 1)对象Mark线程2(cup 2)
访问同步块,获取monitor10(重量级锁)-
成功(加锁)10(重量级锁)-
执行同步块10(重量级锁)访问同步块,获取monitor
退出同步块(解锁)01(无锁)自旋重试
-10(重量级锁)成功加锁
-10(重量级锁)执行同步块
-01(无锁)退出同步块(解锁)

自旋失败的情况

线程1(cup 1)对象Mark线程2(cup 2)
访问同步块,获取monitor10(重量级锁)-
成功(加锁)10(重量级锁)-
执行同步块10(重量级锁)访问同步块,获取monitor
执行同步块10(重量级锁)自旋重试
执行同步块10(重量级锁)自旋重试
执行同步块10(重量级锁)自旋重试
执行同步块10(重量级锁)阻塞
  • Java6之后自旋锁是自适应,比如对象刚刚一次自旋操作成功过,那么这次自旋成功的可能性会高,就多自旋几次;反之,就减少自旋次数。
  • 自旋会占用CPU时间,单核CPU自旋就是浪费,多核CPU自旋才能发挥优势。
  • Java 7之后不能控制是否开启自旋功能。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值