AQS原理深度解析:ReentrantLock与CLH队列详解

需积分: 50 21 下载量 123 浏览量 更新于2024-09-06 3 收藏 501KB PDF 举报
AQS(AbstractQueuedSynchronizer)原理详解是关于Java并发编程中一种核心的同步机制,它主要用于ReentrantLock等高级锁的实现。ReentrantLock是最常用的AQS类,它的底层结构是基于CLH(Chaining List Head)队列,这是一种特殊的虚拟队列,没有实际的队列实例,只有节点之间的前后关系。 在AQS中,当一个线程试图获取锁时,它首先调用`nonfairTryAcquire`方法。这个方法会检查当前是否有其他线程正在竞争锁。如果没有(即c字段值为0),线程将尝试通过CAS(Compare and Swap)原子操作将状态值设置为acquires(初始值为1),表示自己正在尝试获取锁。如果成功,当前线程就获得了锁,同时防止其他线程在此时抢占,这就是所谓的非公平锁,它提高了锁的获取效率,但可能会对已经在队列中的线程造成不公平。 如果线程发现已经有其他线程持有锁(c≠0),但自己也持有(可能是重入),它会简单地增加acquires计数并修改状态,实现了一种称为“偏向锁”的优化,这种情况下不需要将线程加入队列,从而提升性能。然而,如果线程确实需要加入队列,如当尝试获取锁失败时,会调用`addWaiter`方法,将自己包装成一个Node并添加到队列的末尾。这是通过基于CAS的无锁(Lock-Free)算法实现的,以避免并发修改队列尾部时可能产生的竞态条件。 在加锁过程中,AQS使用了`LockSupport.park()`方法,这是一个本地方法,它让当前线程进入阻塞状态,实际上是调用了`sun.misc.Unsafe.park()`,最终通过`pthread_mutex_lock`在Linux的内核层实现线程的阻塞。当持有锁的线程调用`unlock()`,它会唤醒队列中的一个等待线程,使之继续执行。 AQS提供了一个高效、灵活的同步框架,它支持自旋锁和阻塞锁的切换,以及公平和非公平的锁策略,这使得Java并发编程中的锁管理更为精细,提高了程序的并发性能和资源利用率。理解和掌握AQS原理对于编写高并发、低阻塞的Java应用程序至关重要。