轻量级锁(CAS)和重量级锁

JVM线程:OS线程 == 1:1

<jdk1.2 重量级锁

(个人见解,尤其在重量级锁方面)

重量级锁和轻量级锁的概念

重量级锁:交给 OS 管理锁的争抢,释放 CPU 资源

轻量级锁:JVM 自己管理锁的争抢(无锁,自旋锁),CPU资源不释放

不上锁时的多线程并发问题

在不上锁的情况下,多个线程可能会出现以下的并发问题
在这里插入图片描述

轻量级锁的实现方式:CAS

在这里插入图片描述
查看现在的值是不是原先读到本地线程的值,是就修改,不是重新读取到本地,继续循环

因为需要一直循环直到修改成功,所以使用 while 循环,所以轻量级锁也叫自旋锁

CAS可能引起的两个问题

ABA问题

在 CAS 判断的过程,可能出现此时数值为原先的值,但是该数值是经过修改后再修改才变成原先的值(0->1->0),此时 CAS 再修改值得到的结果可能和我们想要的结果不同。

例子在这里插入图片描述

如图原本线程期望修改后的栈中元素为 B -> B ,但是由于中间其他线程修改了栈,现在却变成了 B -> C,与期望不同

解决办法

添加一个版本号 version(添加时间戳),区别前后的值

CAS原子性问题

CAS 叫做 compare ans swap ,本质其实也是如下思想(假设原本读入为 0 ,现在需要改变为 1)

if(i == 0) {//在非原子性的情况下,如果条件为true,进入代码块后,i可能会被其他线程改变,导致得到的不是预期结果
    i = 1;
}

所以 CAS 本身的底层实现必须支持原子性;

CAS的底层实现

底层实现是使用了汇编语言的 lock 指令前缀 和 cmpxchg 指令

cmpxchg 指令

作用就是比较并交换操作数,该指令本身不保证原子性

lock 指令前缀

给共享内存上锁,保证在执行指令时 CPU 可以独占资源(在硬件层面上上锁)

多核CPU下并发问题

单核 CPU 时可以不加 lock 指令,因为线程的执行实际要落到 CPU 上的,单核 CPU 的情况下,每一个时刻都只能有一个线程在执行,所以单核下,就是该指令执行时不存在其他线程修改资源的情况

但在多核 CPU 的环境下,某个时刻下是有可能多个线程同时执行代码的,而 cmpxchg 指令不保证原子性,所以我们需要加入 lock 指令前缀对资源进行上锁,保证只有一个 CPU 可以使用该资源

重量级锁

把线程对锁的争抢交给 OS 管理,即让需要获得的锁资源的线程进入阻塞状态,此时 CPU 不再停留在该线程上(即线程释放 CPU 资源);

OS 维护一个等待队列,将需要争抢该锁资源的线程放入队列等待,锁资源释放后,由 OS 唤醒队列的一个线程,获取资源;

等待和唤醒的函数

wait

使线程进入阻塞

notify

唤醒一个现场

重量级锁和轻量级锁的效率问题

当多个线程在争夺锁资源时,使用轻量级锁会 CPU 会把大部分时间花在线程切换上,导致效率低下;

而大部分情况下都只有一个线程会获取到锁资源的情况下,使用重量级锁交给 OS 管理,代价太高,效率低;

故在竞争激烈的情况下选择重量级锁,竞争不激烈的情况下选择轻量级锁

具体情况具体分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值