简述AQS原理
这是一道面试题:简述AQS原理
AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node)来实现锁的分配。
看个AQS(AbstractQueuedSynchronizer)原理图:
AQS,它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。这里volatile是核心关键词,具体volatile的语义,在此不述。state的访问方式有三种:
- getState()
- setState()
compareAndSetState()
AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)。
不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:
- isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
- tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
- tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
- tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- tryReleaseShared(int):共享方式。尝试释放资源,成功则返回true,失败则返回false。
以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程lock()时,会调用tryAcquire()独占该锁并将state+1。此后,其他线程再tryAcquire()时就会失败,直到A线程unlock()到state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证state是能回到零态的。
再以CountDownLatch以例,任务分为N个子线程去执行,state也初始化为N(注意N要与线程个数一致)。这N个子线程是并行执行的,每个子线程执行完后countDown()一次,state会CAS(Compare and Swap)减1。等到所有子线程都执行完后(即state=0),会unpark()主调用线程,然后主调用线程就会从await()函数返回,继续后余动作。
一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一种即可。但AQS也支持自定义同步器同时实现独占和共享两种方式,如ReentrantReadWriteLock。
最新文章
- 自己动手写一个简单的MVC框架(第一版)
- Linux代码的重用与强行卸载Linux驱动
- Nginx初学者指南
- JQuery学习之其他
- linux下在jar包中找类是否存在
- Ajax status状态详解
- vs 2010 Cannot find or open the PDB file
- HDOJ 1202 The calculation of GPA
- [笔记] /etc/init.d/ 下脚本的通用结构
- ico图标在谷歌浏览器中如何显示?
- CSS初了解
- SQL Server 数据库基于备份文件的【一键还原】
- 压力测试Apache
- 原创《如何用vue来轻松的驾驭 html5 webapp的页面体验》
- 【python 3】 集合方法操作汇总
- 构建web应用之——文件上传
- erlang二进制
- iptables log日志记录功能扩展应用:iptables自动配置临时访问策略,任意公网登录服务器
- LeetCode——15. 3Sum
- 【Java】 大话数据结构(18) 排序算法(5) (直接插入排序)
热门文章
- MFC文档应用程序CToolBar:设置两个工具条并列停靠到同一条边上 转
- nRF5 SDK for Mesh( 七 ) BLE MESH 的 架构(rchitecture)
- C语言入门编程思维引导
- 批量kill杀死某些会话session的PL/SQL
- DBA手记-BBED 的说明
- nodejs的事件轮询机制
- ztz11的noip模拟赛T2:查房
- $.post({})请求springmvc -5.x 的方法,没有 返回数据的情况
- Redis全方位详解--磁盘持久化和容灾备份
- PHP的strtotime()函数2038年bug问题