AQS 是 Java 并发包中实现锁的基础,全称是 AbstractQueuedSynchronizer。它定义了一套通用的方法来实现互斥锁、读写锁、信号量等。AQS 的核心思想是使用队列来管理等待锁的线程,当一个线程获取不到锁时,就会被加入到队列中,并在合适的时候被唤醒尝试获取锁。这样可以避免线程的频繁创建和销毁,提高系统的性能
AQS 的实现原理其实挺复杂的。它的核心是一个内部类 Node,每个等待锁的线程都会对应一个 Node 对象。Node 中包含了线程的信息和等待状态。AQS 中维护了一个队列,用于存储等待锁的线程对应的 Node 对象。AQS 中还定义了一些方法,用于获取锁、释放锁、阻塞线程、唤醒线程等。在代码中,AQS 被广泛应用于各种锁的实现,如 ReentrantLock、Semaphore、CountDownLatch 等。AQS 的数据结构是一个队列,用于存储等待锁的线程对应的 Node 对象。AQS 的机制是通过队列来管理等待锁的线程,当一个线程获取不到锁时,就会被加入到队列中,并在合适的时候被唤醒尝试获取锁。这样可以避免线程的频繁创建和销毁,提高系统的性能
基于 AQS 实现的锁的原理其实差不多。比如 ReentrantLock,它是一个可重入锁,也就是说,同一个线程可以多次获取同一个锁。ReentrantLock 的内部实现使用了 AQS,它维护了一个线程的计数器,用于记录当前持有锁的线程的数量。当一个线程第一次获取锁时,计数器加 1,当线程释放锁时,计数器减 1。只有当计数器为 0 时,锁才会被真正释放。ReentrantLock 还支持公平锁和非公平锁两种模式。公平锁是指按照线程请求锁的顺序来分配锁,而非公平锁是指可能会优先分配锁给已经等待了较长时间的线程。Semaphore 是一个信号量,它用于控制同时访问某个资源的线程数量。Semaphore 的内部实现也使用了 AQS,它维护了一个计数器,用于记录当前可用的资源数量。当一个线程请求资源时,如果计数器大于 0,就会减少计数器的值,并允许线程继续执行。当线程释放资源时,就会增加计数器的值。CountDownLatch 是一个倒数器,它用于等待某个事件的发生。CountDownLatch 的内部实现也使用了 AQS,它维护了一个计数器,用于记录需要等待的事件数量。当一个线程调用 await 方法时,就会减少计数器的值,并等待事件的发生。当计数器为 0 时,所有等待的线程都会被唤醒
基于 AQS 实现的锁还有 CyclicBarrier,它是一个循环屏障,用于让一组线程等待彼此到达某个屏障点。CyclicBarrier 的内部实现也使用了 AQS,它维护了一个计数器,用于记录需要等待的线程数量。当一个线程调用 await 方法时,就会减少计数器的值,并等待其他线程到达屏障点。当计数器为 0 时,所有等待的线程都会被唤醒,并继续执行。此外,AQS 还提供了一些其他的方法,如 tryAcquire、tryRelease 等,用于实现锁的获取和释放。AQS 的使用非常灵活,可以根据具体的需求来实现不同类型的锁