1. AQS
1.1 CLH 队列锁
1.2 AbstractQueuedSynchronizer
队列同步器 AbstractQueuedSynchronizer(AQS),是用来构建锁或者其他同步组件的基础框架,它使用了一个 int 成员变量 state 表示同步状态(加锁状态),通过内置的 FIFO 队列来完成资源获取线程的排队工作。
AQS 是基于 CLH 的变种实现。
使用 AQS 实现自己的锁,使用的是模板模式,需要自己实现模板方法:
1.
2.
/**
* 自己实现独占锁,可重入
*/
public class ReenterSelfLock implements Lock {
// 静态内部类,自定义同步器
private static class Sync extends AbstractQueuedSynchronizer {
// 是否处于占用状态
protected boolean isHeldExclusively() {
return getState() > 0;
}
// 当状态为0的时候获取锁
public boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
} else if (getExclusiveOwnerThread() == Thread.currentThread()) {
setState(getState() + 1);
return true;
}
return false;
}
// 释放锁,将状态设置为0
protected boolean tryRelease(int releases) {
if (getExclusiveOwnerThread() != Thread.currentThread()) {
throw new IllegalMonitorStateException();
}
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setState(getState() - 1);
if (getState() == 0) {
setExclusiveOwnerThread(null);
}
return true;
}
// 返回一个Condition,每个 condition 都包含了一个 condition 队列
Condition newCondition() {
return new ConditionObject();
}
}
private final Sync sync = new Sync();
public void lock() {
sync.acquire(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
public boolean isLocked() {
return sync.isHeldExclusively();
}
public boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
}
2. 显式锁
2.1 Lock 接口
标准使用范式是:解锁代码要放在 finally 中,确保业务代码出现异常时,可以解锁。
2. 显式锁
- 可重入锁:加锁线程可再次对同一资源加锁。
ReentrantLock 是可重入锁,synchronized 也是可重入锁。 - 公平锁、非公平锁:先抢锁线程先拿到锁是公平锁,否则为非公平锁。
非公平锁效率更高。
2.1 ReentrantLock
2.2 读写锁:ReadWriteLock、ReentrantReadWriteLock
相对独占锁而言。
读写锁的排斥性:读读不排斥、读写排斥、写写排斥。
public class UseRwLock implements GoodsService {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock getLock = lock.readLock();//读锁
private final Lock setLock = lock.writeLock();//写锁
@Override
public GoodsInfo getNum() {
getLock.lock();
try {
SleepTools.ms(5);
return null;
} finally {
getLock.unlock();
}
}
@Override
public void setNum(int number) {
setLock.lock();
try {
SleepTools.ms(5);
} finally {
setLock.unlock();
}
}
}
2.3 Condition
private Lock kmLock = new ReentrantLock();
private Condition kmCond = kmLock.newCondition();
private Lock siteLock = new ReentrantLock();
private Condition siteCond = siteLock.newCondition();