AQS初探-上篇

一、前述

在java的并发编程中,经常聊到锁【ReentrantLock】、计数器【CountdownLatch】、信号量 【Semaphore】、同步屏障【CyclicBarrier】等。
而这些类的关键核心就在于AQS【AbstractQueuedSynchronizer】,如名所述,抽象的队列式的同步器。
通过对AQS的学习,可以更好的了解理解依赖于它的相关技术实现。
废话不多说,下面就来学习一下传说中的AQS

二、框架

/**
     * The synchronization state.
     */
    private volatile int state;

AQS的整个框架围绕state展开情节,它就像片里的女主角,哈哈哈。
state代表的是共享的资源,在AQS中,用volatile修饰,保证该资源的可见性,具体这个关键字的一系列学习了解,后面再说哈,今天就先围绕state来好好研究一下。
正在吃辣条,真好吃!!

下面是AQS的框架图,网上扣来的,自己的绘画水平太差就不献丑了~~
这是一个网上扣来的图

可以看到这是一个CLH队列,具体为什么叫CLH,与发明它的人有关了[CLH 锁的名字也与他们的发明人的名字相关:Craig,Landin and Hagersten]。
它维护一个state变量[共享资源]与一个FIFO线程等待队列[多线程争用资源被阻塞时进入该队列]。

state的访问方式有三种:

1 getState()
2 setState()
3 compareAndSetState()

AQS定义了两种数据共享方式:

1 独占 比如 ReentrantLock
2 共享 比如 CountdownLatch

不同的同步器争用资源的方式不同,只需要实现共享资源state的获取和释放即可,至于具体线程等待队列的维护[竞争资源入队/唤醒出队],AQS已经在顶层提供实现,自定义同步器主要实现以下几种方法:

1 isHeldExclusively() 该线程是否独占。用到condition才需要实现,比如ReentrantLock
2 tryAcquire(int) 独占方式,尝试获取资源。成功true
3 tryRelease(int) 独占方式,尝试释放资源。成功true
4 tryAcquireShared(int) 共享方式,尝试获取资源,负数失败
5 tryReleaseShared(int) 共享方式,尝试释放资源,true成功

举例:
eg1:
以可重入锁ReentrantLock为例,state初始化为0,代表处于未锁定状态。
A线程lock时,调用tryAcquire独占该锁并将state+1。此后,其他线程调用tryAcquire尝试获取该锁就会失败,
直到unlock()至state为0,即释放锁为止,其他线程才有机会获取该锁。在释放该锁之前,A线程可以重复获取
该锁,每次state+1,这就是可重入的概念。当然获取几次就要释放几次,直到state为0时才完全释放该锁。

eg2:
再以同步计数器CountdownLatch为例,任务分为N个子线程执行,state也初始化为N,N个线程并行执行,每
个线程执行完执行一次countdown(),state会cas减1,直到所有子线程全部执行完state=0,会unpark主调用线
程,然后主调用线程就会await返回,继续后余动作。

贪多嚼不烂,AQS源码细节在下一章详细再看咯

猜你喜欢

转载自blog.csdn.net/qq_28605513/article/details/84193724
AQS