JUC之AbstractQueuedSynchronizer原理

1. 抽象队列同步器(AbstractQueuedSynchronizer,简称AQS),其是一个锁实现框架。ReentrantLock、CountDownLatch、Semaphore、CyclicBarrier都是基于AQS实现的,当然你也可以自己来实现。每一个实现的工具类内部都有一个继承AbstractQueuedSynchronizer的属性sync,工具类获取锁的方法都是调用sync的方法,类似一种代理形式,如ReentrantLock的lock()方法调用AbstractQueuedSynchronizer.acquire()方法,CountDownLatch.awai()调用AbstractQueuedSynchronizer.acquireSharedInterruptibly()等等。

 

2. 既然众多同步工具都是依赖AQS来实现的,那么其内部实现原理是什么呢?

AbstractQueuedSynchronizer用一个volatile int state属性来标识同步状态(加锁状态、释放锁状态),假设A线程获取锁,state变成加锁状态,此时B线程也来获取锁,由于锁被A线程持有,AQS将B线程添加到一个队列里面,并阻塞B线程,B线程等待。当A线程释放锁后,state变成释放锁状态,此时B从队列里弹出并解除阻塞去获取锁。

那么AQS至少包含以下构件:

1). 同步状态,一个volatile int state(代表共享资源),并且对该状态的持有又分为独占模式和共享模式

2). 一个存储等待线程的队列(CLH队列)

3).  阻塞与解除阻塞线程的工具(LockSupport.park/unpark)

 

3、线程的阻塞与解除阻塞

首先AbstractQueuedSynchronizer维护两个双链表队列,一个队列用于存储排队获取锁的线程,称之为等待队列,该队列由AbstractQueuedSynchronizer自身维护;另外一个队列是AbstractQueuedSynchronizer.ConditionObject(内部类)来维护的,称之为条件队列,这个队列的主要用途就是当线程内部执行lock.await()方法时,将该线程添加到这个队列里面。当线程获取signal()信号时,将该线程从条件队列移除,同时添加到等待队列里面。

posted @ 2017-05-12 22:59  joenali  阅读(130)  评论(0编辑  收藏  举报