UnSafe实现+CAS思想(自旋锁)

本文介绍了自旋锁和非自旋锁的概念及其在多线程环境中的使用。自旋锁允许线程尝试获取锁直至成功,而不进入阻塞状态,减少了线程切换开销,适用于低并发、短同步任务。非自旋锁在获取不到锁时会进入阻塞,等待唤醒。以AtomicInteger的getAndIncrement方法为例,展示了CAS(比较并交换)操作如何实现自旋锁。自旋锁消耗CPU资源,适合并发不高、同步任务简单的场景。而AtomicInteger的getAndIncrement方法利用了Unsafe类的CAS操作,确保线程安全。关键词包括:自旋锁、非自旋锁、并发控制、线程安全、AtomicInteger、CAS操作、Unsafe类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自旋锁:获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,一直循环到获取锁为止。
非自旋锁: 获取不到锁,线程就进入阻塞状态。等待 CPU 唤醒,再去获取
想象以下场景:某线程去获取锁(可能是自旋锁 or 非自旋锁),然而锁现在被其他线程占用了。它两获取锁的执行流程就如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nx7IljzW-1650758877574)(https在这里插入图片描述]
😕/img-blog.csdnimg.cn/5d49d27596c04b97ab2c7b25d6e52d27.png)
自选锁的好处与坏处:避免了线程切换的开销,但可能会消耗CPU资源。
适用场景:并发不能太高,避免一直自旋不成功,线程执行的同步任务不能太复杂,耗时比较短 。在手写自旋锁时,先了解自选锁的实现原理,在java.util.concurrent的包中,里面的原子类基本都是自旋锁的实现。我们看看做常用的 AtomicInteger 类,它里面有个 getAndIncrement 方法,然后底下的有个调用Unsafe 的 getAndAddInt 方法 源码如下:
在这里插入图片描述
参数:this为创建atomicInteger实例对象、valueOffset为内存偏移量、1为修改值
大致意义:先获取内存储值:var5,通过var1和var2获取期望值与var5进行比较,若为true则var5+var4并返回,否则就一直循环。
UnSafe:是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为Java中CAS操作的执行依赖于Unsafe类的方法。
CAS :它是一条CPU并发原语,它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的,也就是说在执行过程中不允许被中断保证了当前线程的数据时一致的。在这里插入图片描述
输出结果为: 第一条允许修改,修改值为2019。第二条不允许因为期望值(原生)5被A修改
在这里插入图片描述
因此在多线程环境下,原子操作是保证线程安全的重要手段,但只能保证一个线程,并且消耗资源大。
理由在以下案例: 通过CAS(比较并修改)+自旋锁展示:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值