首页IT科技并发逻辑漏洞(并发基础之AQS)

并发逻辑漏洞(并发基础之AQS)

时间2025-09-17 03:45:17分类IT科技浏览5138
导读:目录...

目录

什么AQS

AQS原理

重点1:CLH队列​

重点2:state 状态

AQS 两种资源共享方式

1) Exclusive(独占)

2) Share(共享)

AQS 模板方法运用

补充知识CAS

CAS的优点

CAS的缺点

缺点解决办法

总结

什么AQS

AQS是位于java.util.concurrent.locks 包下的 AbstractQueuedSynchronizer类                ,是构建同步器和锁的基础框架                。我们可以通过继承AbstractQueuedSynchronizer 创建自己的同步器                        。比如我们常用的JUC并发包下面的CountDownLatch                、ReentrantLock                        、Semaphore等等都是源于AQS实现的并发工具类       。

AQS原理

核心思想是多个线程访问共享资源                        ,如果一个线程发现共享资源没有被占用       ,则将资源设定为锁定状态且当前线程设为占用线程        ,如果一个线程发现共享资源已经被占用                        ,则需要等待占用线程释放资源               ,当然当占用线程释放资源的时候AQS会通知其他等待线程进行资源抢占        。在AQS实际源码中是通过state 状态在标识资源是否占用        ,通过CLH FIFO虚拟双向队列来实现将最近的等待线程放在队列末尾                        。

重点1:CLH队列

如图所示CLH是一个虚拟的双向队列                        ,是通过state的值实现线程等待排序在队列末尾               。队列head 头部是当前资源占用工作线程               ,node1-node n 则是资源被锁定后等待的线程节点        。在实际的资源占用过程中,根据是否公平锁来确定是顺序占用资源和抢占式占用资源                        。

重点2:state 状态

如上图所示                        ,线程获取资源是否被占用是通过获取 state 状态来实现               。AQS源码已经给出获取       、设置        、通过CAS修改state 的方法。此时我们可以理解为:

 1                        、线程获取state 发现为 0                        ,说明没有线程占用则占用该资源,并通过CAS将state 置为 1

2               、如果该线程有重入的情况则继续增加state 的值                ,重入几次就增加几次

3        、线程出方法则需要释放state值                       ,也就是减少state

4                        、当state值为0 的时候标识线程执行完毕解除占用       ,此时AQS唤醒其他线程可以占用资源

AQS 两种资源共享方式

1) Exclusive(独占)

只有一个线程能执行                ,如 ReentrantLock                        。又可分为公平锁和非公平锁,ReentrantLock 同时支持两种锁                       。根据ReentrantLock定义                        ,我们可知公平锁是根据队列的等待顺序占用资源       ,非公平锁是所有的等待线程抢占资源。

2) Share(共享)

运行多个线程对资源共享        ,比如JUC并发工具CountDownLatch               、Semaphore等都是运行多个线程访问资源                。

AQS 模板方法运用

AQS内置很多的操作方法                        ,比如获取锁 tryAcquire()、释放锁 tryRelease()                        、超时获取tryAcquireNanos()                       、响应中断 acquireInterruptibly()等操作方法

在实际的运用过程中               ,我们可以直接继承AQS从而轻易的获取这些方法来实现我们的同步器                       。

当前JUC下的并发工具类都是基于AQS来实现自己的功能的        ,我们现在来鉴赏一下       。

比如可重入锁ReentrantLock                        ,我们进入源码查看               ,ReentrantLock内部类继承AQS:

我们ReentrantLock超时获取锁/释放锁也都是调用AQS超时获取锁/释放锁的方法:

当然其他对资源状态和队列的操作方法都是基于AQS实现的,对于JUC中其他的并发工具类也是如此                        ,都是基于AQS实现                。

补充知识CAS

CAS是Compare and Swap 的缩写                       ,也就是比较和替换,是JUC最核心最基础的理论                        。原理是基于三个数据 主存值V、线程副本值A                、需要修改为值B       。当且仅当主存值V等于线程副本值A的时候                ,才能将数据修改为B        。

CAS的优点

CAS是乐观锁                       ,且一直自旋等待锁       ,所以性能很高                        。

CAS的缺点

ABA问题                ,如果我们先将值C修改为D,再修改为C                        ,CAS会认为此数据没有修改               。

缺点解决办法

1                       、加版本号

2       、JAVA JUC atomic下提供AtomicStampedReference包装类

总结

AQS是位于java.util.concurrent.locks 包下的 AbstractQueuedSynchronizer类       ,是构建同步器和锁的基础框架        。JAVA JUC并发包下的工具类都是基于AQS实现        ,其原理都是通过state状态来确定线程是否占用资源                        ,未拿到锁的线程则放置在CLH虚拟双向队列末尾               ,后续通过AQS通知抢占资源                        。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
下载饿了吗(本地部署element-plus文档) html+css+javascript网页设计简明教程答案(实验一 基于CSS+HTML+JS开发简单个人网站)