AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类。 阅读Java的并发包源码你会发现这个类是整个java.util.concurrent的核心之一,也可以说是阅读整个并发包源码的一个突破口。

比如读ReentrantLock的源码你会发现其核心是它的一个内部类Sync:

整个包中很多类的结构都是如此,比如Semaphore,CountDownLatch都有一个内部类Sync,而所有的Sync都是继承自AbstractQueuedSynchronizer。 所以说想要读懂Java并发包的代码,首先得读懂这个类。

AQS简核心是通过一个共享变量来同步状态,变量的状态由子类去维护,而AQS框架做的是:

  • 线程阻塞队列的维护
  • 线程阻塞和唤醒

共享变量的修改都是通过Unsafe类提供的CAS操作完成的。AbstractQueuedSynchronizer类的主要方法是acquirerelease,典型的模板方法, 下面这4个方法由子类去实现:

protected boolean tryAcquire(int arg)
protected boolean tryRelease(int arg)
protected int tryAcquireShared(int arg)
protected boolean tryReleaseShared(int arg)

acquire方法用来获取锁,返回true说明线程获取成功继续执行,一旦返回false则线程加入到等待队列中,等待被唤醒,release方法用来释放锁。 一般来说实现的时候这两个方法被封装为lockunlock方法。

下面的SimpleLock类实现了一个最简单非重入的互斥锁的功能,实际上它就是ThreadPoolExecutor$Worker的实现(以后的文章会提到这个类)。

class SimpleLock extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -7316320116933187634L; public SimpleLock() { } protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
} protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
} public void lock() {
acquire(1);
} public boolean tryLock() {
return tryAcquire(1);
} public void unlock() {
release(1);
} public boolean isLocked() {
return isHeldExclusively();
}
}
public static void main(String[] args) throws InterruptedException {
final SimpleLock lock = new SimpleLock();
lock.lock(); for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println(Thread.currentThread().getId() + " acquired the lock!");
lock.unlock();
}
}).start();
// 简单的让线程按照for循环的顺序阻塞在lock上
Thread.sleep(100);
} System.out.println("main thread unlock!");
lock.unlock();
}

运行上面的测试代码,结果如下:

main thread unlock!
9 acquired the lock!
10 acquired the lock!
11 acquired the lock!
12 acquired the lock!
13 acquired the lock!
14 acquired the lock!
15 acquired the lock!
16 acquired the lock!
17 acquired the lock!
18 acquired the lock!

会发现等待的线程是按照阻塞时的顺序依次获取到锁的。 这是因为AQS是基于一个叫CLH lock queue的一个变种来实现线程阻塞队列的,我们下一篇文章就来简单了解下CLH lock queue。

后续文章计划如下:

  • 《Java并发包源码学习之AQS框架(二)CLH lock queue和自旋锁》
  • 《Java并发包源码学习之AQS框架(三)LockSupport》
  • 《Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析》
  • 《Java并发包源码学习之AQS框架(五)ConditionObject源码分析》

  ……

  • 《Java并发包源码学习之锁(一)概述》
  • 《Java并发包源码学习之锁(二)ReentrantLock源码分析》

  ……

  • 《Java并发包源码学习之线程池(一)概述》
  • 《Java并发包源码学习之线程池(二)ThreadPoolExecutor源码分析》

  ……

学习Java并发包源码的初衷是为了搞清之前遇到的一个问题,其实很早之前就打算看这块的源码但一直没看下去,所以说 看源码一定要有目的不能为了看而看。

Java并发包源码学习之AQS框架(一)概述的更多相关文章

  1. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  2. Java并发包源码学习之AQS框架(三)LockSupport和interrupt

    接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...

  3. Java并发包源码学习之AQS框架(二)CLH lock queue和自旋锁

    上一篇文章提到AQS是基于CLH lock queue,那么什么是CLH lock queue,说复杂很复杂说简单也简单, 所谓大道至简: CLH lock queue其实就是一个FIFO的队列,队列 ...

  4. Java并发包源码学习系列:AQS共享式与独占式获取与释放资源的区别

    目录 Java并发包源码学习系列:AQS共享模式获取与释放资源 独占式获取资源 void acquire(int arg) boolean acquireQueued(Node, int) 独占式释放 ...

  5. Java并发包源码学习系列:CLH同步队列及同步资源获取与释放

    目录 本篇学习目标 CLH队列的结构 资源获取 入队Node addWaiter(Node mode) 不断尝试Node enq(final Node node) boolean acquireQue ...

  6. Java并发包源码学习系列:ReentrantLock可重入独占锁详解

    目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterrupti ...

  7. Java并发包源码学习系列:ReentrantReadWriteLock读写锁解析

    目录 ReadWriteLock读写锁概述 读写锁案例 ReentrantReadWriteLock架构总览 Sync重要字段及内部类表示 写锁的获取 void lock() boolean writ ...

  8. Java并发包源码学习系列:详解Condition条件队列、signal和await

    目录 Condition接口 AQS条件变量的支持之ConditionObject内部类 回顾AQS中的Node void await() 添加到条件队列 Node addConditionWaite ...

  9. Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类

    目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...

随机推荐

  1. Java Servlet完全教程

    Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求. Servle ...

  2. 【Alpha版本】 第八天 11.16

    一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 昨天完成任务 今天完成任务 明天要做任务 问题困难 心得体会 胡泽善 完成我要应聘的列表显示,完成账户信息设置界面 完成我要应聘的详情显 ...

  3. 高性能JavaScript(您值得一看)

    众所周知浏览器是使用单进程处理UI更新和JavaScript运行等多个任务的,而同一时间只能有一个任务被执行,如此说来,JavaScript运行了多长时间就意味着用户得等待浏览器响应需要花多久时间. ...

  4. 命名实参和可选实参 Named and Optional Arguments

    1. 利用“命名实参”,您将能够为特定形参指定实参,方法是将实参与该形参的名称关联,而不是与形参在形参列表中的位置关联. static void Main(string[] args) { Conso ...

  5. Bootstrap基本类和组件学习二

    一.联系方式:(自带鼠标的移动动画) 1.头文件CSS <link rel="shortcut icon" href="favicon.ico"> ...

  6. 基本药目录sop

    http://db.yaozh.com/basicdir 基本药物 编辑 "基本药物"的概念, 由世界卫生组织于1977年提出,指的是能够满足基本医疗卫生需求,剂型适宜.保证供应. ...

  7. ubuntu下增加中文编码

    在Ubuntu中,利用命令:locale,来查看系统的语言环境 参考:http://blog.chinaunix.net/uid-94449-id-2002589.html Windows的默认编码为 ...

  8. Java——列表框:JList

    import java.awt.Container; import java.awt.GridLayout; import java.awt.event.WindowAdapter; import j ...

  9. 使用Diagnose服务查看Azure网站诊断信息

    注意:当前操作只针对"基本"和"标准"模式的网站(也就是有独立实例的网站) 登陆网站的kudu模式:http://{yoursitename}.scm.chin ...

  10. TeXmacs - 所见即所得 - 专业排版软件

    所见即所得,支持中文,很好用, 容易奔溃,奔溃进入不了程序时,删除文件夹 C:\Users\Perelman\AppData\Roaming\TeXmacs