AQS的基本功能
AbstractQueuedSynchronizer(AQS)是一个用于构建锁和同步器的框架,它提供了一系列的方法来管理同步状态、线程的阻塞与唤醒、队列等内容。
AQS有哪些能力,都对应什么方法
getState():这个方法返回当前同步状态的值,它是一个整数,用于表示资源的可用数量或状态。
这个资源是指什么?——同步状态(synchronization state)
- setState(int state):这个方法设置同步状态的值,当资源可用时,可以将状态设置为1;当资源不可用时,可以将状态设置为0。
- compareAndSetState(int expect, int update):这个方法比较当前同步状态的值和期望的值,如果相等,则更新同步状态为更新值。这个方法通常用于实现资源的独占获取和释放。
- tryAcquire(int acquires):这个方法尝试获取资源,如果当前同步状态的值大于0,则将其减1并返回true;如果同步状态的值等于0,则将其加1并返回false。这个方法通常用于实现资源的独占获取。
- tryRelease(int releases):这个方法尝试释放资源,如果当前同步状态的值小于队列长度,则将其加1并返回true;如果同步状态的值等于队列长度,则将其减1并返回false。这个方法通常用于实现资源的独占释放。
- tryParkAndBlock():这个方法尝试将当前线程阻塞并加入等待队列,直到被唤醒或超时。这个方法通常用于实现阻塞式的线程等待。
- unpark(Thread thread):这个方法唤醒指定线程,使其从阻塞状态中恢复并继续执行。这个方法通常用于实现线程的唤醒。
这些方法提供了基本的同步和协调多线程的功能,可以用于构建各种不同的锁和同步器。在继承AQS并实现自定义同步器时,可以调用这些方法来实现独占式获取和释放资源、阻塞和唤醒线程等操作。
AQS中的队列
在AbstractQueuedSynchronizer(AQS)中,存在两种队列,分别是:
- 条件队列:当线程需要进行条件等待时,会被加入到条件队列中。条件队列是ConditionObject上的一个成员变量,用于管理等待特定条件的线程。
- 阻塞队列:当线程需要获取资源时,会被加入到阻塞队列中。阻塞队列是AQS本身的一个成员变量,用于管理等待获取资源的线程。
这两种队列都是基于链表实现的,每个节点都封装了一个线程对象。在获取AQS锁时,这些进入到阻塞队列中的线程会按照在队列中的排序先后尝试获取
怎么理解AbstractQueuedSynchronizer的阻塞队列和条件队列?
阻塞队列:
阻塞队列是一个线程队列,用于存储等待获取锁的线程。
当一个线程尝试获取锁但未能成功时,它会进入阻塞队列,等待其他线程释放锁。
阻塞队列通常在同步器(如ReentrantLock)中使用,以确保只有一个线程可以获得锁并执行临界区代码。
阻塞队列通常采用链表或数组实现,以支持线程的插入、删除和排序操作。
条件队列:
条件队列是一个线程队列,用于存储等待特定条件的线程。
当一个线程需要等待特定条件满足时,它会进入条件队列,等待其他线程唤醒。
条件队列通常在实现条件变量(如CountDownLatch、Semaphore)时使用。
条件队列中的线程在条件满足时被唤醒并重新竞争锁,以执行特定任务或继续执行。
AQS提供了阻塞和唤醒线程的管理机制
- 对于阻塞机制,当一个线程尝试获取锁或满足特定条件时,如果不能立即获取到,它会进入阻塞状态。AQS使用LockSupport的park和unpark方法实现线程的阻塞和唤醒。LockSupport.park方法阻塞当前线程,除非/直到LockSupport.unpark被执行。对unpark的调用不会被计数,所以park之前的多个unpark只会解除阻塞一个park。
- 对于唤醒机制,当其他线程释放了锁或满足了特定条件时,被唤醒的线程将被重新放入队列中,等待下一次的获取锁或条件满足的机会。这种方式实现了线程的唤醒,使得其他线程可以继续执行。
- 在AQS中,阻塞和唤醒机制是通过维护一个队列来实现的。当一个线程尝试获取锁或满足条件时,它会将自己加入到队列中等待。当锁或条件被释放时,队列中的下一个线程将被唤醒并尝试获取锁或满足条件。这种方式实现了线程的排队等待和有序竞争,确保了同步的正确性和公平性。
AbstractQueuedSynchronizer(AQS)在实现阻塞与唤醒能力时,主要使用了以下方法:
- park()和unpark(Thread thread):这两个方法用于阻塞和唤醒线程。park()方法会使当前线程进入阻塞状态,直到被唤醒或超时;而unpark(Thread thread)方法则会唤醒指定的线程,使其从阻塞状态中恢复并继续执行。
- park(Object blocker)、parkNanos(Object blocker, long nanos)和parkUntil(Object blocker, long deadline):这些方法用于实现更细粒度的线程阻塞。它们允许指定一个阻塞对象(blocker),该对象主要用于问题排查和系统监控。
JAVA中有哪些组件继承了AbstractQueuedSynchronizer的能力
- ReentrantLock:这是Java并发包中提供的一个可重入的互斥锁。它使用AQS来实现其同步机制。
- CountDownLatch:这是一个同步工具类,它允许一个或多个线程等待,直到在指定的计数器达到零时才会继续执行。它也使用了AQS。
- Semaphore:这是一个信号量,它提供了一种限制对共享资源的访问数量的机制。它同样基于AQS实现。
- FutureTask:这是一个可以取消的异步计算任务。它使用AQS来管理任务的执行和结果的获取。
- ThreadPoolExecutor:这是一个用于执行异步任务的线程池,它使用AQS来管理任务的执行和线程的生命周期。
对AQS的这些极具抽象的能力还是难以理解。看看有具体功能的实现子类。
------------------------------分割线-------------------------------------
待续...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。