让我来为您详细讲解“Java并发系列之AbstractQueuedSynchronizer源码分析(概要分析)”的攻略且提供两条示例说明。
1. 概要分析
1.1 AQS简介
AQS(AbstractQueuedSynchronizer)
是java.util.concurrent(J.U.C)中的一个关键内部类,是JUC包中实现各种同步器的基础。AQS
是实现锁、线程安全的核心基础。
1.2 AQS的内部结构
AQS
是一个队列同步器,它的内部定义了一个基本锁的框架,它维护一个先进先出的等待队列来管理锁状态。
在AQS
的实现中,一般你只需要关注三个方法:tryAcquire
,tryRelease
和tryAcquireShared
。其中tryAcquire
和tryRelease
对于排他锁(独占模式)是必要的,tryAcquireShared
通常对于共享锁是必要的。它们分别尝试对锁的获取和释放操作,如果成功则返回true,否则返回false。
AQS
的核心是CLH队列算法
。在AQS
机制中,每一个由线程调用acquire
方法(或者是其变种)而被阻塞的线程都会被封装为一个FIFO的队列
1.3 AQS实现原理
总体思路:通过内部CLH队列
(双向链表)来实现线程之间的排队、等待、唤醒、争抢
等功能。
实现原理是基于状态位state
,读写操作都是原子性的,我们可以通过CAS实现高效的并发控制。state
的操作也是AQS
的关键。
每一个节点都包含一个先驱节点的引用和一个继承节点的引用。操作时通过一个FIFO队列
来保证节点是按照请求锁的线程的顺序来进行排序的。
1.4 AQS示例代码
下面是一个使用AQS
的简单示例代码:
private final Sync sync = new Sync();
private static final class Sync extends AbstractQueuedSynchronizer {
protected boolean tryAcquire(int acquires) {
return compareAndSetState(0, 1);
}
protected boolean tryRelease(int releases) {
return compareAndSetState(1, 0);
}
protected int tryAcquireShared(int acquires) {
// acquire shared mode
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int releases) {
// release shared mode
return true;
}
}
public void lock() { sync.acquire(1); }
public boolean tryLock() { return sync.tryAcquire(1); }
public void unlock() { sync.release(1); }
public Condition newCondition() { return sync.newCondition(); }
该示例代码定义了一个Lock
实现,通过Sync
类继承AQS
类实现的。
2. 示例说明
2.1 ReentrantLock类
我们都知道在Java
并发中的ReentrantLock
是这些并发类中必不可少的一个,它内部调用ReentrantLock
的线程都会获得一个可重入的锁
,并且其他线程只有在它释放这个锁后才能获得这个锁。
ReentrantLock
是通过AQS
机制来实现的,对于ReentrantLock
而言,主要关注的是它内部调用的sync.tryAcquire()
和sync.tryRelease()
方法。
2.2 CountDownLatch类
接下来,我们来看另一个实际示例:CountDownLatch
。
CountDownLatch
是一个同步工具类,用于协调多个线程之间的同步。
假设我们有一个程序,其中有一个主线程,它需要等待几个其他线程执行完毕后再继续执行,这个时候CountDownLatch
就非常合适。
在Java中,CountDownLatch
就是通过AQS
实现的同步工具,它的基本思想就是:线程要等待的是某些工作的完成,而负责完成这些工作的各个线程都告诉该
AQS对象完成了自己的工作,等到所有的工作都完成后,所有阻塞的线程才同时醒来继续执行
。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发系列之AbstractQueuedSynchronizer源码分析(概要分析) - Python技术站