Java并发编程序列之JUC底层AQS

Java并发编程序列之JUC底层AQS

谈到JUC,Lock接口,大家肯定都会用。最常用的ReentrantReadWriteLock等。本文作为JUC的开头,先把Lock接口和AQS的API说一下,然后说清楚Lock和AQS的关系。文章结构:

  1. Lock,AQS的相关API
  2. AQS和Lock接口的关系

1. Lock,AQS的相关API

Lock接口相关要实现API:

Lock相关API

AQS相关要实现API:

AQS相关API

AQS提供给程序员调用的API:

AQS提供的模板方法:

2. AQS和Lock接口的关系

好了,看了上面的API,或者根本懒得看的API,大家肯定是一脸**,不过没关系,下面我通过一张图来说清楚AQS(队列同步器)和Lock接口的关系。

稍微说一下:当我们要实现一个Lock接口的实现类时,是肯定要依赖一个AQS(队列同步器的),这是为什么呢,因为队列同步器帮我们维护是线程阻塞和释放的逻辑,比如,线程竞争锁时,当一个线程没有竞争到时,要把它丢进一个FIFO的队列,当获取到锁的线程释放锁时,要通知在队列里的线程出来竞争。大家想一想,如果让你自己维护,那不是累死了??所以JDK给我们提供了AQS,暴露出来了一些底层的API,让我们去覆盖,然后有一些模板API来调用我们底层的API,并且维护好队列。这样我们就只用把精力放在获得到锁和没有获得到锁的逻辑上了.不用管没有线程获得锁后以及线程释放锁后如何通知其他线程怎么维护。如图所示,红色箭头的起始点其实就是AQS提供给我们的模板API,我们要实现的API只需要调用AQS提供给我们的state相关API(绿色箭头尾部)来维护是否获取到锁就可以了。最后Lock接口的API调用模板方法或者我们实现的API来实现锁的语义.

注意点:

  • 在Lock接口中调用锁的释放语义时不要直接调用我们实现的API,tryRelease之类的API,而是调用模板方法中的Release相关API,因为它底层维护了通知其他线程竞争锁的语义.
  • 在Lock接口的实现中是可以调用我们实现的API中的tryAcquire,因为没有拿到锁就返回了,没有用到模板维护的队列,以及模板维护的超时等功能.

结语

好了,打完收工。Hava a good day .
下期将自定义一个Lock来运用本文所讲的内容。