这个类简称AQS,如果我们要实现的功能是有获取和释放这两个操作,并且获取操作总是能够阻塞,那么我们就应该创建一个锁,并且这个锁继承AbstractQueuedSynchronizer,因为无论是获取,还是释放,都是依赖状态的操作
二:AQS中的state属性
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return STATE.compareAndSet(this, expect, update);
}
使用state来管理状态的类非常多,例如
ReentranLock中的锁用该字段表示持有锁的线程已经持有了多少次(可重入)
Semaphore中的锁用该字段表示剩余的许可数量
FutureTask中的锁用该字段表示任务的状态(未开始,运行,完成,取消)
二:AQS中的exclusiveOwnerThread属性
exclusiveOwnerThread表示在同步互斥锁的功能中,当前持有锁的线程是哪个,exclusiveOwnerThread与state两个属性配合使用,可以实现任意独占锁功能
/**
* 表示当前持有锁的线程
*/
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
虽然concurrent包提供了能实现所有需求的类,但是本文出于学习其原理和其思想的目的,有必要说一下AQS最重要的编程范式,也就是说,你要使用AQS,那么就必须得按照这个代码模板去写,因为Doug Lee就是这样要求的,这也是模板设计思想,AQS中有下面四个常用的模板方法
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
当实现上锁解锁相关需求的时候,实现这个需求的类叫做A,那么类A中,应该有一个内部类,这个内部类就是锁,用来辅助类A来实现获取和释放操作,比如ReentranLock与它的内部类Sync之间的关系,下面例子实现了共享锁这样一个功能,最开始,任何线程都调用await,都无法执行下去,都会阻塞,当有任意一个线程调用signal的时候,之前调用await的那些线程都开始执行
public class MysShareLock {
SharedSync sharedSync = new SharedSync();
public void await() {
sharedSync.acquireShared(0);
}
public void signal() {
sharedSync.releaseShared(0);
}
// 这个内部类就是锁
private class SharedSync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryReleaseShared(int arg) {
setState(1);
return true;
}
// 大于0就能获取到锁,注意与等于0的区别,看注释
@Override
protected int tryAcquireShared(int arg) {
if (getState() == 1) {
return 1;
}
return -1;
}
}
//
public static void main(String[] args) throws InterruptedException {
MysShareLock tl = new MysShareLock();
new Thread(() -> {
System.out.println("T1调用await");
tl.await();
System.out.println("T1调用await完毕");
}).start();
new Thread(() -> {
System.out.println("T2调用await");
tl.await();
System.out.println("T2调用await完毕");
}).start();
new Thread(() -> {
System.out.println("T3调用await");
tl.await();
System.out.println("T3调用await完毕");
}).start();
Thread.sleep(3000);
new Thread(() -> {
System.out.println("T4要让T1,T2,T3都继续执行");
tl.signal();
}).start();
}
}
下面的例子是一个互斥锁的实现
public class MysMutexLock {
Sync sync = new Sync();
public void luck() {
sync.acquire(0);
}
public void unluck() {
sync.release(0);
}
private class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryRelease(int arg) {
setState(1);
return true;
}
// true表示可以获取锁
@Override
protected boolean tryAcquire(int arg) {
if (getState() == 1) {
return true;
}
return false;
}
}
public static void main(String[] args) throws InterruptedException {
MysMutexLock tl = new MysMutexLock();
new Thread(() -> {
System.out.println("T1调用luck");
tl.luck();
System.out.println("T1调用luck完毕");
}).start();
new Thread(() -> {
System.out.println("T2调用luck");
tl.luck();
System.out.println("T2调用luck完毕");
}).start();
new Thread(() -> {
System.out.println("T3调用luck");
tl.luck();
System.out.println("T3调用luck完毕");
}).start();
Thread.sleep(3000);
new Thread(() -> {
System.out.println("T4释放锁,T1,T2,T3不一定谁能获取到锁");
tl.unluck();
}).start();
while (true) {
}
}
}