问题

(1)AQS的定位?

(2)AQS的重要组成部分?

(3)AQS运用的设计模式?

(4)AQS的总体流程?

简介

AQS的全称是AbstractQueuedSynchronizer,它的定位是为Java中几乎所有的锁和同步器提供一个基础框架。

在之前的章节中,我们一起学习了ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch的源码,今天我们一起来对AQS做个总结。

状态变量state

AQS中定义了一个状态变量state,它有以下两种使用方法:

(1)互斥锁

当AQS只实现为互斥锁的时候,每次只要原子更新state的值从0变为1成功了就获取了锁,可重入是通过不断把state原子更新加1实现的。

(2)互斥锁 + 共享锁

当AQS需要同时实现为互斥锁+共享锁的时候,低16位存储互斥锁的状态,高16位存储共享锁的状态,主要用于实现读写锁。

互斥锁是一种独占锁,每次只允许一个线程独占,且当一个线程独占时,其它线程将无法再获取互斥锁及共享锁,但是它自己可以获取共享锁。

共享锁同时允许多个线程占有,只要有一个线程占有了共享锁,所有线程(包括自己)都将无法再获取互斥锁,但是可以获取共享锁。

AQS队列

AQS中维护了一个队列,获取锁失败(非tryLock())的线程都将进入这个队列中排队,等待锁释放后唤醒下一个排队的线程(互斥锁模式下)。

Condition队列

AQS中还有另一个非常重要的内部类ConditionObject,它实现了Condition接口,主要用于实现条件锁。

ConditionObject中也维护了一个队列,这个队列主要用于等待条件的成立,当条件成立时,其它线程将signal这个队列中的元素,将其移动到AQS的队列中,等待占有锁的线程释放锁后被唤醒。

Condition典型的运用场景是在BlockingQueue中的实现,当队列为空时,获取元素的线程阻塞在notEmpty条件上,一旦队列中添加了一个元素,将通知notEmpty条件,将其队列中的元素移动到AQS队列中等待被唤醒。

模板方法

AQS这个抽象类把模板方法设计模式运用地炉火纯青,它里面定义了一系列的模板方法,比如下面这些:

// 获取互斥锁
public final void acquire(int arg) {// tryAcquire(arg)需要子类实现if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}
// 获取互斥锁可中断
public final void acquireInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();// tryAcquire(arg)需要子类实现if (!tryAcquire(arg))doAcquireInterruptibly(arg);
}
// 获取共享锁
public final void acquireShared(int arg) {// tryAcquireShared(arg)需要子类实现if (tryAcquireShared(arg) < 0)doAcquireShared(arg);
}
// 获取共享锁可中断
public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();// tryAcquireShared(arg)需要子类实现if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);
}
// 释放互斥锁
public final boolean release(int arg) {// tryRelease(arg)需要子类实现if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;
}
// 释放共享锁
public final boolean releaseShared(int arg) {// tryReleaseShared(arg)需要子类实现if (tryReleaseShared(arg)) {doReleaseShared();return true;}return false;
}

获取锁、释放锁的这些方法基本上都穿插在ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch的源码解析中了,现在看他们是不是舒服多了,如果一开始就看这些源码,难免会很晕。

需要子类实现的方法

上面一起学习了AQS中几个重要的模板方法,下面我们再一起学习下几个需要子类实现的方法:

// 互斥模式下使用:尝试获取锁
protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();
}
// 互斥模式下使用:尝试释放锁
protected boolean tryRelease(int arg) {throw new UnsupportedOperationException();
}
// 共享模式下使用:尝试获取锁
protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();
}
// 共享模式下使用:尝试释放锁
protected boolean tryReleaseShared(int arg) {throw new UnsupportedOperationException();
}
// 如果当前线程独占着锁,返回true
protected boolean isHeldExclusively() {throw new UnsupportedOperationException();
}

这几个方法为什么不直接定义成抽象方法呢?

因为子类只要实现这几个方法中的一部分就可以实现一个同步器了,所以不需要定义成抽象方法。

总结

今天我们大概讲了下AQS中几个重要的组成部分,搞明白了这几个结构,AQS对你将没有任何秘密可言,当然面试的时候能把这几个点答清楚,面试官也会眼前一亮的。

(1)状态变量state;

(2)AQS队列;

(3)Condition队列;

(4)模板方法;

(5)需要子类实现的方法;

彩蛋

经过前面的学习,您能简要描述一下AQS获取互斥锁的大体流程吗?

这里彤哥就不作答了,相信学习完前面的内容,答这道题不是个问题了,答不上来的还需要把下面的推荐阅读好好多看几遍^^

推荐阅读

1、 死磕 java同步系列之开篇

2、 死磕 java魔法类之Unsafe解析

3、 死磕 java同步系列之JMM(Java Memory Model)

4、 死磕 java同步系列之volatile解析

5、 死磕 java同步系列之synchronized解析

6、 死磕 java同步系列之自己动手写一个锁Lock

7、 死磕 java同步系列之AQS起篇

8、 死磕 java同步系列之ReentrantLock源码解析(一)——公平锁、非公平锁

9、 死磕 java同步系列之ReentrantLock源码解析(二)——条件锁

10、 死磕 java同步系列之ReentrantLock VS synchronized

11、 死磕 java同步系列之ReentrantReadWriteLock源码解析

12、 死磕 java同步系列之Semaphore源码解析

13、 死磕 java同步系列之CountDownLatch源码解析

欢迎关注我的公众号“彤哥读源码”,查看更多源码系列文章, 与彤哥一起畅游源码的海洋。

死磕java_死磕 java同步系列之AQS终篇(面试)相关推荐

  1. 死磕java_死磕 java同步系列之AQS起篇

    问题 (1)AQS是什么? (2)AQS的定位? (3)AQS的实现原理? (4)基于AQS实现自己的锁? 简介 AQS的全称是AbstractQueuedSynchronizer,它的定位是为Jav ...

  2. 死磕 java同步系列之AQS起篇

    问题 (1)AQS是什么? (2)AQS的定位? (3)AQS的实现原理? (4)基于AQS实现自己的锁? 简介 AQS的全称是AbstractQueuedSynchronizer,它的定位是为Jav ...

  3. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  4. 死磕 java同步系列之终结篇

    简介 同步系列到此就结束了,本篇文章对同步系列做一个总结. 脑图 下面是关于同步系列的一份脑图,列举了主要的知识点和问题点,看过本系列文章的同学可以根据脑图自行回顾所学的内容,也可以作为面试前的准备. ...

  5. 死磕 java同步系列之ReentrantReadWriteLock源码解析

    问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...

  6. java 同步锁_死磕 java同步系列之自己动手写一个锁Lock

    问题 (1)自己动手写一个锁需要哪些知识? (2)自己动手写一个锁到底有多简单? (3)自己能不能写出来一个完美的锁? 简介 本篇文章的目标一是自己动手写一个锁,这个锁的功能很简单,能进行正常的加锁. ...

  7. 明翰Java教学系列之集合框架篇V0.2(持续更新)

    文章目录 传送门 前言 什么是集合框架 集合框架体系 Collection接口 `Set接口` `HashSet` LinkedHashSet TreeSet EnumSet Queue接口 Prio ...

  8. 死磕 java同步系列之开篇

    简介 同步系列,这是彤哥想了好久的名字,本来是准备写锁相关的内容,但是java中的CountDownLatch.Semaphore.CyclicBarrier这些类又不属于锁,它们和锁又有很多共同点, ...

  9. 2019死磕java面试题_死磕 java同步系列之开篇

    简介 同步系列,这是彤哥想了好久的名字,本来是准备写锁相关的内容,但是java中的CountDownLatch.Semaphore.CyclicBarrier这些类又不属于锁,它们和锁又有很多共同点, ...

最新文章

  1. 报名 | AI TIME 6 论道机器翻译——离我们还有多远?
  2. 「镁客·请讲」全盛科技吕盛:将侦测、跟踪、识别、管控融于一体,做低空安全守卫者...
  3. server正式的环境性能测试nginx-php 指着寻求突破的表现
  4. c#爬虫-1688官网自动登录
  5. Redis 常用操作命令,非常详细
  6. win2003 sp2+iis 6.0上部署.net 2.0和.net 4.0网站的方法
  7. VM安装失败 Failed to create the requested registry key Key:installer Error:1021
  8. C++新特性探究(18.3):C++11 weak_ptr智能指针
  9. 专注于分布式存储计算技术及其应用url http://www.nosqlnotes.net/
  10. linux kvm虚拟化ha,基于RHEL6.3-KVM三节点虚拟机命令行搭建HA
  11. 大数据在企业中的运用
  12. itex将html转成pdf加水印,Springboot 中集成itextpdf HTML转PDF并添加水印(支持中文)
  13. 实用软件工程(张海藩)复习笔记
  14. 知名歌手凌晨跳楼自杀:他为什么要走上绝路
  15. 贝叶斯定理,从白袜到飞机失事再到人工智能
  16. 技术问答-5 String StringBuilder StringBuffer
  17. uni-app 省市区选择器
  18. 村淘是什么,农村淘宝有什么用?如何知道宝贝是否加入村淘
  19. 与贸易有关的知识产权协议 (转)
  20. 10个精选一线互联网架构思考与实践

热门文章

  1. 52 - 算法 - LeetCode 28 - 实现 strStr() -kmp
  2. c 抄了java 多少东西,几款Java开发者必备常用的工具,准点下班不在话下
  3. python sqlite3写入内存_Python SQLite内存缓存
  4. Python+tkinter打造类似于IDLE的代码编辑器(83行源码)
  5. 警惕Python编程中异常处理结构可能的坑
  6. Python使用标准库urllib模拟浏览器爬取网页内容
  7. 《Python程序设计开发宝典》第一波转发积攒活动中奖名单
  8. Python使用扩展库numpy计算矩阵加权平均值
  9. jpetstore开发实战--(1)
  10. java接口自动化+博客园_java+接口自动化+eclipse之-----环境搭建