这是一道面试题:简述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。

最新文章

  1. 自己动手写一个简单的MVC框架(第一版)
  2. Linux代码的重用与强行卸载Linux驱动
  3. Nginx初学者指南
  4. JQuery学习之其他
  5. linux下在jar包中找类是否存在
  6. Ajax status状态详解
  7. vs 2010 Cannot find or open the PDB file
  8. HDOJ 1202 The calculation of GPA
  9. [笔记] /etc/init.d/ 下脚本的通用结构
  10. ico图标在谷歌浏览器中如何显示?
  11. CSS初了解
  12. SQL Server 数据库基于备份文件的【一键还原】
  13. 压力测试Apache
  14. 原创《如何用vue来轻松的驾驭 html5 webapp的页面体验》
  15. 【python 3】 集合方法操作汇总
  16. 构建web应用之——文件上传
  17. erlang二进制
  18. iptables log日志记录功能扩展应用:iptables自动配置临时访问策略,任意公网登录服务器
  19. LeetCode——15. 3Sum
  20. 【Java】 大话数据结构(18) 排序算法(5) (直接插入排序)

热门文章

  1. MFC文档应用程序CToolBar:设置两个工具条并列停靠到同一条边上 转
  2. nRF5 SDK for Mesh( 七 ) BLE MESH 的 架构(rchitecture)
  3. C语言入门编程思维引导
  4. 批量kill杀死某些会话session的PL/SQL
  5. DBA手记-BBED 的说明
  6. nodejs的事件轮询机制
  7. ztz11的noip模拟赛T2:查房
  8. $.post({})请求springmvc -5.x 的方法,没有 返回数据的情况
  9. Redis全方位详解--磁盘持久化和容灾备份
  10. PHP的strtotime()函数2038年bug问题