Java中的Lock锁,都是基于AQS,也就是AbstractQueuedSynchronizer。那么AbstractQueuedSynchronizer又是基于什么原理来做锁的呢?
一:锁原理
1. 怎么算获取到了锁?
AQS内置了一个volatile int state字段,利用CAS保证并发安全,当state=0表示没没有线程占用。只要线程设置了state(比如置为1,如果
是可重入锁,state可以>1),就表示获取了锁。
2. 线程竞争时如何保存竞争的线程?
AQS内置了一个双链表,当线程存在竞争时,会先放入这个双链表的尾部。当然,这个放入的动作,也要保证并发安全,这里也是使用了
CAS原子操作,死循环执行这个放入动作直至成功。
3. 竞争线程保存后如何获取锁?
AQS做的很简单,直接死循环尝试获取锁直至成功。具体思路为:
3.1 取当前线程所属节点的上一个节点A。
3.2 如果节点A为头结点,则当前线程尝试获取锁。
3.3 没有获取到锁,则循环3.1 、 3.2
3.4 当获取到锁后,将当前节点置为头结点。这样,排在后边的节点,就会开始获取锁。
之所以要先判断上一个节点为头结点才尝试获取锁,主要有两个原因:
一:CAS操作相对于单纯的判断更加吃CPU。
二:这样保证了获取锁的公平性,方便公平锁的实现。
4. 锁释放
各种不同类型的锁,锁释放思路不同。但是都要刷 state=state-1。
二:AQS的优点
可以实现语义更加丰富的锁,比如读写锁、公平锁、非公平锁。
标签:Java,AQS,AbstractQueuedSynchronizer,获取,state,线程,节点 From: https://www.cnblogs.com/kingcode/p/17982990