Java并发包源码学习之AQS框架(一)概述
2015-03-10 19:39
986 查看
AQS其实就是
比如读
整个包中很多类的结构都是如此,比如
AQS简核心是通过一个共享变量来同步状态,变量的状态由子类去维护,而AQS框架做的是:
线程阻塞队列的维护
线程阻塞和唤醒
共享变量的修改都是通过
acquire方法用来获取锁,返回true说明线程获取成功继续执行,一旦返回false则线程加入到等待队列中,等待被唤醒,release方法用来释放锁。 一般来说实现的时候这两个方法被封装为
下面的
运行上面的测试代码,结果如下:
会发现等待的线程是按照阻塞时的顺序依次获取到锁的。 这是因为AQS是基于一个叫
后续文章计划如下:
《Java并发包源码学习之AQS框架(二)CLH lock queue和自旋锁》
《Java并发包源码学习之AQS框架(三)LockSupport》
《Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析》
《Java并发包源码学习之AQS框架(五)ConditionObject源码分析》
……
《Java并发包源码学习之锁(一)概述》
《Java并发包源码学习之锁(二)ReentrantLock源码分析》
……
《Java并发包源码学习之线程池(一)概述》
《Java并发包源码学习之线程池(二)ThreadPoolExecutor源码分析》
……
学习Java并发包源码的初衷是为了搞清之前遇到的一个问题,其实很早之前就打算看这块的源码但一直没看下去,所以说 看源码一定要有目的不能为了看而看。
java.util.concurrent.locks.AbstractQueuedSynchronizer这个类。 阅读Java的并发包源码你会发现这个类是整个
java.util.concurrent的核心之一,也可以说是阅读整个并发包源码的一个突破口。
比如读
ReentrantLock的源码你会发现其核心是它的一个内部类
Sync:
整个包中很多类的结构都是如此,比如
Semaphore,
CountDownLatch都有一个内部类
Sync,而所有的Sync都是继承自
AbstractQueuedSynchronizer。 所以说想要读懂Java并发包的代码,首先得读懂这个类。
AQS简核心是通过一个共享变量来同步状态,变量的状态由子类去维护,而AQS框架做的是:
线程阻塞队列的维护
线程阻塞和唤醒
共享变量的修改都是通过
Unsafe类提供的CAS操作完成的。
AbstractQueuedSynchronizer类的主要方法是
acquire和
release,典型的模板方法, 下面这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方法用来释放锁。 一般来说实现的时候这两个方法被封装为
lock和
unlock方法。
下面的
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框架(二)CLH lock queue和自旋锁
- Java并发包源码学习之AQS框架(三)LockSupport和interrupt
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
- Java并发包源码学习之AQS框架(三)LockSupport和interrupt
- Java学习笔记(十)collections框架概述
- Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(1)
- .Java程序员从笨鸟到菜鸟之(四十七)细谈struts2(九)内置拦截器和自定义拦截器详解(附源码) 分类: 学习专区 框架Struts2 Java程序员从笨鸟到菜鸟 2012-05-08 12:
- Java并发框架Executor学习笔记
- java并发-AQS.ObjectCondition源码解析
- Java并发框架——AQS之原子性如何保证?
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
- Java并发框架——AQS之原子性如何保证?
- Java并发框架——AQS之如何使用AQS构建同步器
- 【新技术,学习、商业均可】HTML5 全新高大尚后台 bootstrap springmvc mybatis java企业级通框架源码入门
- Java集合源码学习笔记(一)集合框架概览
- Java并发框架Executor学习笔记
- Java并发框架——什么是AQS框架
- Java并发框架——AQS中断的支持
- Java并发框架——AQS之阻塞与唤醒
- Java并发框架??AQS中断的支持