前面几篇文章分析了AQS的实现在并发中的运用,今天来整体的总结下他们的区别。

四大实现功能简介

对AQS的实现的运用有以下四个类ReentrantLock、CountDownLatch、Semaphore、ReentrantReadWriteLock,梳理下这几个类的主要作用。

ReentrantLock:可重入锁、独占锁,当一个线程获取到资源,也就是获取到锁的时候,其他所有需要获取锁的线程都会阻塞,直到线程释放锁。

CountDownLatch:闭锁,初始化一个值n,线程调用await方法会阻塞当前线程,每调一个countDown一次n就减一,当减到0时所有调用await方法阻塞的线程被唤醒重新继续执行。可以实现多个线程等待一个线程,也可以实现一个线程等待多个线程执行完再执行;

Semaphore:信号量,就好像初始化一定数量的许可证,每个线程先获取许可证,只有获取成功了才可以继续执行,没有获取成功的就只能等待其他线程执行完释放许可后再被唤醒去获取许可;

ReentrantReadWriteLock:读写锁,支持共享方式多个线程同时获取资源,也支持排他方式只能有一个线程能够获取,用读锁的时候表示支持其他读锁访问,写锁的时候就只允许一个线程访问;

实现方式

上面这四个类都是利用AQS来直接实现他们的功能的,他们自身并没有太多的属性或者复杂的方法,而他们利用的都是AQS提供的模板方法,比如ReentrantLock.lock()方法调用的是AQS的acquire方法,semaphore.release()调用的是AQS的releaseShared方法。这几个类会让线程阻塞的方法都是调用AQS的acquire类型方法,会唤醒等待线程的方法都是调用Release类型的方法。

而AQS的acquire与Release类型方法实际上都是只有两步操作,第一步是尝试判断或者修改AQS属性state的值,第二步是根据第一个执行的结果来把线程放到等待队列中或者唤醒等待队列中的线程再次执行。

而AQS的acquire与Release类型方法的第一步操作只依赖4个方法tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared的返回结果。而这四个方法在AQS中是没有内容的是直接抛出异常的方法,所以要使用AQS就必须去重写这些方法,4个工具类就是通过对四个方法的不同实现来实现他们不同的功能。

不同的实现

ReentrantLock实现了两个方法tryAcquire、tryRelease,tryAcquire方法是尝试state递增,tryRelease尝试递减,当把state从0变到1时表示线程获取成功,会把当前线程设置为这个锁的持有者,后面的递增或者递减都只能是这个线程才能操作,实现可重入,当把state由1设置成0的时候会清空锁的持有线程,表示线程释放锁;

CountDownLatch实现了tryAcquireShared、tryReleaseShared两个方法,tryAcquireShared方法是判断state是否等于0,tryReleaseShared会尝试对state递减,当减到0时才会返回true,表示可以唤醒其他线程了;

Semaphore实现了tryAcquireShared、tryReleaseShared两个方法,tryAcquireShared同样也是尝试减少state的值,tryReleaseShared则尝试增加state的值;

ReentrantReadWriteLock因为包含两个锁的实现WriteLock、ReadLock;所以他实现了AQS的四个方法,WriteLock使用tryAcquire、tryRelease方法,ReadLock使用tryAcquireShared、tryReleaseShared方法,读写锁通过利用一个state来实现读、写标记并且完全不会冲突,比上面三个稍微复杂一点,这里不细说了,可以去看我的上一篇文章。

4大方法

讲了4个类对4大方法的实现,那么来整体看看他们的整体对AQS使用详情。总体详情如下图:

打开网易新闻 查看更多图片

4个工具类的所有方法总的来说都是调用的AQS的5个模板方法,5个模板方法在根据上面提到的4个需要自我实现的方法来修改或校验state值,修改成功或者验证成功再调用AQS提供的几个方法把当前线程放到等待链表中并阻塞或者唤醒等待链表中的线程。

总结

AQS在并发中的使用就是这4个类,在AQS提供了一系列的模板方法以供外部使用,每个模板方法都是调用一个需要使用者实现的方法来和内部实现的方法。需要实现的方法实际上就是对state的不同操作,内部实现的方法则是对线程的具体处理。

所以实际上AQS是利用模板方法模式,提供一系列对线程操作的方法,只不过要正确使用这些方法就必须先实现对state的操作。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!