什么是AQS
全称AbstractQueuedSynchronizer
AQS实现是基于CLH队列锁
CLH同步队列是一个FIFO双向队列,这三张图是来解释状态改变的过程,关于CLH可以自行查询
多个线程时,myPred指向上一个存储的线程,并且自循检查前一个线程是否释放锁,自循一定次数后进入阻塞状态
上一个线程的locked等于false时,当前线程就可以获取到锁。
AQS使用方式
实现见下面锁可重入示例代码
AQS的设计模式
模版模式:具体实现交给子类去实现。自己要实现同步锁,重写模版方法就可以实现。
AQS中的核心方法
tryAcquire和tryRelease方法。
AQS主要通过核心成员变量state来判断是否获取到锁。
了解ReentrantLock锁
- 锁的公平与非公平
- 公平锁
- 非公平锁
区别在于公平锁判断当前线程在队列中前面是否还有其他线程
- 锁的可重入
同一个加锁方法,递归调用依然可以拿到锁,不会出现卡死的情况。
- 例子:
static final Lock lock = new ReenterSelfLock();
public void reenter(int x) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":递归层级:"+x);
int y = x - 1;
if (y==0) return;
else{
reenter(y);
}
} finally {
lock.unlock();
}
}
public void test() {
class Worker extends Thread {
public void run() {
System.out.println(Thread.currentThread().getName());
SleepTools.second(1);
reenter(3);
}
}
// 启动3个子线程
for (int i = 0; i < 3; i++) {
Worker w = new Worker();
w.start();
}
- 如何实现可重入锁:
/**
*类说明:实现独占锁,可重入
*/
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();
}
}
/* 仅需要将操作代理到Sync上即可*/
private final Sync sync = new Sync();
public void lock() {
System.out.println(Thread.currentThread().getName()+" ready get lock");
sync.acquire(1);
System.out.println(Thread.currentThread().getName()+" already got lock");
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public void unlock() {
System.out.println(Thread.currentThread().getName()+" ready release lock");
sync.release(1);
System.out.println(Thread.currentThread().getName()+" already released lock");
}
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));
}
}
在AQS的tryAcquire和tryRelease方法中分别对state本身加减