AQS锁框架
须知,在操作系统层面只有两种锁,一种是mutex(互斥锁),另一种是自旋锁(基于CAS实现的),剩下的所有锁,都是基于mutex 和 cas 来实现的。
1.什么是AQS锁框架?
Java在目前的版本中(1.8),一共有两套锁体系,一种是Synchronize关键字,一种是AQS。
- synchronize关键字,是JVM来实现的,也就是所谓的C++来实现的。此篇不做过多解释。
- AQS锁框架,全程AbstractQueuedSynchronizer(抽象队列同步器)。从名字可以看出三点,抽象,队列,同步器。抽象:表示他可以扩展成各种锁,队列:表示没有获取锁的线程都在排队,同步器:用来控制线程获取锁的组件。ps:这是一个叫Doug Lea的大佬写的,后来被收编了。
2.AQS的组成
AQS框的组成,分为两个组件。第一同步器,第二队列。
2.1 同步器
找到同步器的源码,看一下成员属性,大概就知道同步器有什么东西了。首先我们看顶级类AbstractOwnableSynchronizer,(IDEA工具,光标放在类名上,按住crit+F12)
从名字上看,独占owner线程。大致猜出来,它是放抢到那个锁的那个线程对象的。然后看AbstractQueuedSynchronizer类。
可以看到head,tail,state,一堆offset和unsafe(这些东西都是CAS会用到的,此处先不用理会)
- head:Node类型,head头部的意思,node节点,此处是队列的头部节点(先记住OK)。
- tail:Node类型,tail尾部的意思,node节点,此处是队列的尾部节点(先记住OK)。
- state:Int类型,状态。此处是记录有没有线程获取锁的状态,如有就加1。
由此我们基本可画出同步器的样子,大概长这个样子。
2.2 阻塞队列
查看AbstractQueuedSynchronizer的内部类,Node类。依然是查看字段。
可以看到,分为4部分:
- nextWaiter,下一个节点的状态:共享和独占状态,SHARED(共享),EXCLUSIVE(独占)。
- waitStatus等待状态,有五个值。CANCELLED,SIGNAL,CONDITION,PROPAGATE,0。
- 前置节点,后置节点:prev,next。
- 线程对象的引用,thread。
由此我们基本可画出队列的样子,大概长这个样子。
因为,AQS是一个框架,所以就会有很多的实现,每个实现用到了不同的特性(某几个字段)。所以无须纠结。到此大致明白了AQS框架的组成,具体如何来调度线程的逻辑,大多数都是在子类中实现的。