返回
循序渐进理解AQS(1):站在源头的锁的实现
见解分享
2023-10-21 07:08:38
引言
在多线程并行编程中,锁是协调线程访问共享资源不可或缺的工具,而AbstractQueuedSynchronizer(简称AQS)是Java并发编程中构建锁和同步器的基石。本文旨在以循序渐进的方式,从源头的锁的实现角度,带领读者理解AQS的精髓。
锁的本质
锁的本质在于控制线程对共享资源的访问,确保一次只有一个线程能够访问该资源。在实现锁时,需要解决两个核心问题:
- 互斥性: 保证任意时刻至多有一个线程持有锁。
- 公平性: 保证等待锁的线程能够按顺序公平地获得锁。
一个简单的锁实现
最简单的锁实现可以利用Java内置的synchronized
public class SimpleLock {
private boolean locked = false;
public void lock() {
while (locked) {
try {
wait();
} catch (InterruptedException e) {
// 忽略中断异常
}
}
locked = true;
}
public void unlock() {
locked = false;
notifyAll();
}
}
这个简单的锁实现了互斥性,但没有公平性。当多个线程同时尝试获取锁时,获取锁的顺序是不确定的。
AQS:一个灵活高效的锁框架
AQS提供了构建锁和同步器的通用框架,它定义了一个抽象基类AbstractQueuedSynchronizer
,并提供了许多钩子方法和状态属性,允许开发者灵活地实现各种锁和同步器。
AQS的核心思想
AQS的核心思想是:将锁的状态抽象为一个整型变量state
,并通过tryAcquire
和release
两个方法来对状态进行操作。
- tryAcquire: 尝试获取锁。如果成功,返回
true
;否则,返回false
。 - release: 释放锁。
实现互斥性
互斥性通过将state
变量设置为一个非零值来实现。当一个线程获取锁时,它将state
设置为一个非零值。当另一个线程尝试获取锁时,它会发现state
不为零,从而返回false
,表示无法获取锁。
实现公平性
公平性通过引入一个队列来实现。当一个线程无法获取锁时,它会将自己加入队列。当锁被释放时,队列中的第一个线程将获得锁。
小结
本文从源头的锁的实现角度入手,介绍了锁的本质,讨论了一个简单的锁的实现,并阐述了AQS的框架思想和核心机制。在后续的文章中,我们将继续深入探讨AQS的具体实现,分析其高效性和灵活性的秘密。