返回

从源码揭秘AbstractQueuedSynchronizer的幕后机制

后端

AbstractQueuedSynchronizer (简称AQS) 是 Java 并发编程中一个重要的同步器类,它提供了各种同步原语的支持,包括独占锁、共享锁、重入锁和条件队列等。AQS 的设计非常巧妙,它使用了一个双向链表来管理等待线程,并通过 CAS 操作来实现锁的获取和释放。本文将从 AQS 的源码出发,深入分析其关键机制和运作流程,帮助读者从底层理解 AQS 在 Java 并发编程中的重要作用。

独占锁和共享锁

AQS 中最基本的概念是独占锁和共享锁。独占锁允许只有一个线程同时访问共享资源,而共享锁允许多个线程同时访问共享资源。AQS 通过一个 state 变量来表示当前的锁状态,state 的值可以是 0、1、2 或负数。当 state 为 0 时,表示锁是未锁定的;当 state 为 1 时,表示锁被一个线程独占;当 state 为 2 或更大的正数时,表示锁被多个线程共享;当 state 为负数时,表示锁被一个线程独占,并且该线程正在等待其他线程释放共享锁。

重入锁

AQS 支持重入锁,即一个线程可以多次获取同一把锁。当一个线程获取锁时,AQS 会将该线程的重入计数器加 1;当该线程释放锁时,AQS 会将该线程的重入计数器减 1。只有当重入计数器为 0 时,AQS 才会真正释放锁。

条件队列

AQS 还提供了一个条件队列,用于支持线程等待和唤醒。当一个线程需要等待某个条件满足时,它可以调用 AQS 的 await 方法将自己加入条件队列;当条件满足时,另一个线程可以调用 AQS 的 signal 或 signalAll 方法唤醒条件队列中的线程。

AQS 的运作流程

AQS 的运作流程可以分为以下几个步骤:

  1. 当一个线程需要获取锁时,它会调用 AQS 的 acquire 方法。
  2. acquire 方法首先尝试通过 CAS 操作将 state 的值从 0 改为 1,如果成功,则表示该线程成功获取了锁;否则,表示锁已经被其他线程获取了。
  3. 如果该线程没有成功获取锁,它会将自己加入等待队列,然后进入等待状态。
  4. 当锁被释放时,AQS 会唤醒等待队列中的线程。
  5. 唤醒的线程会再次尝试通过 CAS 操作将 state 的值从 0 改为 1,如果成功,则表示该线程成功获取了锁;否则,该线程会再次进入等待状态。

结语

AQS 是 Java 并发编程中一个非常重要的同步器类,它提供了各种同步原语的支持,包括独占锁、共享锁、重入锁和条件队列等。AQS 的设计非常巧妙,它使用了一个双向链表来管理等待线程,并通过 CAS 操作来实现锁的获取和释放。本文从 AQS 的源码出发,深入分析了其关键机制和运作流程,帮助读者从底层理解 AQS 在 Java 并发编程中的重要作用。