AQS


 
AQS介绍:
AbstractQuenedSynchronizer抽象的队列式同步器。
是一个底层锁机制,内部使用了模板方法设计模式,定义了独占式共享式两种资源共享方式。
很多同步类都是依赖AQS实现的。
比如
1.Exclusive:独占,只有一个线程能执行,如ReentrantLock
2.Share:共享,多个线程可以同时执行,如Semaphore、CountDownLatch、CyclicBarrier
3.独占+共享:ReadWriteLock(读共享,写独占)
 
AQS原理:
AQS就是基于一个链表实现的双向队列(CLH),用volatile修饰共享变量state,线程通过CAS去改变state,成功则获取锁成功,失败则进入等待队列,等待被唤醒。队列里每个Node都存放了线程和头尾关系。

 
基于AQS实现自定义同步类:
是基于模板方法模式的
1.使用者继承AbstractQueuedSynchronizer并重写指定的方法(对state的获取和释放)
isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
tryAcquire(int):独占方式。尝试获取资源
tryRelease(int):独占方式。尝试释放资源
tryAcquireShared(int):共享方式。尝试获取资源。
tryReleaseShared(int):共享方式。尝试释放资源。】
2.将AQS组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法,这是模板方法模式很经典的一个运用。
 
 
例:ReentrantLock:
重写tryAcquire()、tryRelease(),实现了可重入逻辑。 
tryAcquire:                                                                                        tryRelease:
 if(state=0)时,                                                                                      每次state -1
当前线程CAS尝试获取独占资源,成功 return true;                        if(state == 0){
else if(当前线程 是 独占资源的线程 ),                                                当前线程释放独占资源
state+1, return true。                                                                          }
else 
return false;
 
所以同一线程  lock多少次,就要unlock多少次。
(他的公平锁实现只是加了一层判断:是否有顺序在本线程前面的在队列排队)

独占锁获取详细过程:
1.本线程 CAS尝试获取独占锁2次
2.获取失败后,线程 CAS自旋尾插 到队列
3.在队列中,自旋 (判断如果前节点是头节点,且获取独占锁成功,则 return。  否则 设置前节点状态为SIGNAL(释放本节点,会通知唤醒下个节点),调用LookSupport.park阻塞本线程。)
4.本线程等待被唤醒后,继续3内自旋的过程。
 
独占锁释放详细过程:
1.释放锁,并判断并唤醒后续节点

 

可中断式获取锁详细过程:其他与独占锁一样,不同点是 在自旋获取失败,线程将要阻塞的时候,会直接中断线程,抛出中断异常。

超时等待式获取锁:其他与独占锁一样,不同点是,自旋时 设置了一个超时时间,(阻塞时也设置了一个超时时间)

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2020-11-21 17:39  匿了匿了  阅读(114)  评论(0编辑  收藏  举报