AQS和CAS是什么?

一、AQS

AQS全称abstractQueuedSynchronizer,它是一个抽象类,队列同步器,常用的实现有ReentrantLock和ReadWriteLock。

作用:构建锁、释放锁、同步队列。

参数

我们首先要了解AQS中的重要参数:

head:记录队列中头部节点;

tail:记录队列中尾部节点;

state:记录队列中等待访问线程数量,通过volatile关键字修饰,保证该参数对所有参数可见且有序(这里的有序是指的是在内存上有序访问);

note内部类:一个双向队列;

thread:当前占用资源线程;

实现方式

AQS采用的是乐观锁,乐观锁其实不是真实的锁,它只是在代码层面通过CAS算法或对比版本号来防止并发,实现锁的作用。

1、当一个线程请求资源时,首先要获取锁资源,就是通过CAS算法,判断内存上的state值是否为0,也就是队列中是否有阻塞线程,如果没有,那么就可以直接将新值赋值到内存地址上,然后进行创建note节点,head、tail都指向该note节点,记录当前线程,state+1操作等等;如果有阻塞队列,也不会直接存入队列,而是会再次尝试获取一次锁,如果这次还获取失败,那就存入队列,这就实现了加锁的过程。

2、当一个线程操作完资源以后,如果存在head节点,并且head指向节点中的waitState不为0,则唤醒head指向的节点,将AQS中的state设置为0,head指向的节点中的waitState的值设为0,唤醒head节点对应线程,重新通过CAS算法竞争锁资源,这就是释放锁的过程。

通过加锁和释放锁来实现队列同步。

二、CAS

CAS全称compareAndSwap,它是一种算法。

作用:可以实现加锁效果,它仅仅是实现了和加锁一样的效果,它并不是一种锁,它可以防止并发访问出错。

实现:线程请求内存资源,资源不加锁,哪个线程都可以取,取出来怎么操作都可以,写入内存时再进行比较,比较的内容就是从内存中取出的数据和此时内存中的数据是否一样,如果一样就认为在这个时间段没有其他线程访问,可以安全写入;如果不一样,则取回新数据重新操作,然后重新写入到内存,这个时候写入内存时重新比较,如果又不一样,表明在这个时间段被其他线程修改了,这种情况就会再去取回数据再进行操作和比较,这就是我们所说的自旋,直到一样时才写入。

扩展:这里有个非常著名的ABA问题,就是我第一个线程取出内存数据为A,操作完以后变成数据B准备写入到内存,这个期间第二个线程把它修改成了B,第三个线程又把它改成了A,这个时候我们写入时发现还是A,会认为这个时间段没有其他线程操作,这就出现了ABA问题。

解决办法:加一个版本号就能解决这个问题,我们在每一次修改值的时候加一个版本号,如果当前的版本号和写入之前的版本号不一致的话,就可以知道在这个时间段有其他线程访问过这个值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lqkj蓝海

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

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

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

打赏作者

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

抵扣说明:

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

余额充值