AQS和CAS粗略介绍

1、AQS

是什么:全称 abstractQueuedSynchronizer,一个抽象类,队列同步器。常见的实现有ReentrantLock、ReadWriteLock

有什么用:构建锁、释放锁、同步队列。

怎么实现:

先看AQS中的重要参数:

head:记录队列中头部节点

tail:记录队列中尾部节点

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

note内部类:一个双向队列

thread:当前占用资源线程

好了,下边介绍AQS如何构建锁、释放锁,实现队列同步:

这里首先说一下,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算法竞争锁资源。这就是释放锁过程。

通过枷锁、释放锁实现队列同步。

2、CAS

是什么:全称compareAndSwap 顾名思义 比较与计算,它就是一种算法

有什么用:可以实现加锁效果,只是同样的效果,它并不是一种锁,就是能防止并发访问出错

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

当然了,这里面有个很著名的ABA问题,什么意思呢,就是我第一个线程取出内存数据为A,操作完变成B准备写入内存,这期间有第二个线程把它修改成了B,第三个线程又把它修改回了A,这时候我写入时发现还是A,会认为期间没有其他线程操作,这就出现了ABA问题。

怎么解决呢,解决的办法也很简单,就是普遍的加版本号,即每次修改内存的值都加一个版本号,只要我上次拿到的版本号和写入时的版本号不一样就证明被其他线程动过了,这时候是继续写入还是退回就看业务需要了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值