AQS(AbstractQueuedSynchronizer)抽象队列同步器
AQS是并发编程包里面的一个抽象类
实现的子类有哪些,基于AQS实现了,线程池里面用到了,显示锁用到了,读写锁用到了,信号量用到了…
JDK并发里面的同步组件的一个基础的构件,用来构建同步组件
AQS中比较重要的成员变量:state 同步状态,
/**
* The synchronization state.
*/
private volatile int state;
模板方法的设计模式
模版方法:
做一件事情 dosomething
Dosomething (){
doFirst();
doSecond();
…
doTenth();
}
用模版方法做蛋糕:
/**
* 类说明:抽象蛋糕模型
*/
public abstract class AbstractCake {
protected abstract void shape();/*造型*/
protected abstract void apply();/*涂抹*/
protected abstract void brake();/*烤面包*/
/*做个蛋糕 */
public final void run(){
this.shape();
this.apply();
this.brake();
}
}
/**
* 类说明:芝士蛋糕
*/
public class CheeseCake extends AbstractCake {
@Override
protected void shape() {
System.out.println("芝士蛋糕造型");
}
@Override
protected void apply() {
System.out.println("芝士蛋糕涂抹");
}
@Override
protected void brake() {
System.out.println("芝士蛋糕烘焙");
}
}
/**
* 类说明:奶油蛋糕
*/
public class CreamCake extends AbstractCake {
@Override
protected void shape() {
System.out.println("奶油蛋糕造型");
}
@Override
protected void apply() {
System.out.println("奶油蛋糕涂抹");
}
@Override
protected void brake() {
System.out.println("奶油蛋糕烘焙");
}
}
/**
* 类说明:生产蛋糕
*/
public class MakeCake {
public static void main(String[] args) {
AbstractCake cheeseCake = new CheeseCake();
AbstractCake creamCake = new CreamCake();
cheeseCake.run();
creamCake.run();
}
}
芝士蛋糕造型
芝士蛋糕涂抹
芝士蛋糕烘焙
奶油蛋糕造型
奶油蛋糕涂抹
奶油蛋糕烘焙
实现自己的同步类的时候就是用模版方法,只要实现其中几个方法就行了
比如要实现独占锁,就要实现AQS里面的独占的方法:
tryAcquire本身是没有任何实现的,调用它会抛出异常,这个方法是要我们去实现的
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
比如要实现共享同步组件类:
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
实现一个类似于ReentrantLock的锁 (显示锁)
显示锁继承Lock接口
要实现独占锁,拿锁lock()、释放锁unlock() 一定要实现,这两个方法如何实现,就要借助AQS
/**
*类说明:实现我们自己独占锁,不可重入
*/
public class SelfLock implements Lock {
// 静态内部类,自定义同步器
private static class Sync extends AbstractQueuedSynchronizer {
/*判断处于占用状态*/
@Override
protected boolean isHeldExclusively() {
return getState()==1;
}
/*获得锁*/
@Override
protected boolean tryAcquire(int arg) {
if(compareAndSetState(0,1)){
//Exclusive排他的独占的
//拿到这把锁后就承包了,排他
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
/*释放锁*/
@Override
protected boolean tryRelease(int arg) {
if(getState()==0){
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
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); //acquire方法里面调用的是tryAcquire
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));
}
}
/**
*
*类说明:测试我们自己的独占锁的实现
*/
public class TestMyLock {
public void test() {
final Lock lock = new SelfLock();
class Worker extends Thread {
public void run() {
lock.lock();
System.out.println(Thread.currentThread().getName());
try {
SleepTools.second(1);
} finally {
lock.unlock();
}
}
}
// 启动4个子线程
for (int i = 0; i < 4; i++) {
Worker w = new Worker();
//w.setDaemon(true);
w.start();
}
// 主线程每隔1秒换行
for (int i = 0; i < 10; i++) {
SleepTools.second(1);
//System.out.println();
}
}
//四个线程打印名字
public static void main(String[] args) {
TestMyLock testMyLock = new TestMyLock();
testMyLock.test();
}
}
Thread-0 ready get lock
Thread-2 ready get lock
Thread-2 already got lock
Thread-2
Thread-1 ready get lock
Thread-3 ready get lock
Thread-2 ready release lock
Thread-2 already released lock
Thread-1 already got lock
Thread-1
Thread-1 ready release lock
Thread-1 already released lock
Thread-0 already got lock
Thread-0
Thread-0 ready release lock
Thread-3 already got lock
Thread-3
Thread-0 already released lock
Thread-3 ready release lock
Thread-3 already released lock
调用acquire模版方法,acquire里面的tryAcquire方法是需要我们去实现的
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
AQS的基本思想CLH队列锁
基于链表的自旋锁
CLH三个人的名字头字母即Craig, Landin, and Hagersten (CLH) locks
任意时刻只有一个线程拿到锁,其他的线程在外面排队,拿锁的线程释放了会唤醒线程去竞争锁,没有拿到锁的线程都要排队,一一排好队形成一个链表
凡是要排队的线程,打包成一个QNode,里面至少有三个变量:当前线程、myPred(前驱节点)、locked(=true需要获得锁)
每一个节点都在不停地自旋检测前一个节点有没有释放锁(locked==false)
AQS的基本思想是会不断的自旋,在具体的实现上是双向列表,不会自旋很多次,两次自旋失败后就会把当前线程挂起
回头看Lock的实现
锁的可重入
改一下tryAcquire方法,判断是我自己的话state+1
/**
*类说明:实现我们自己独占锁,可重入
*/
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));
}
}
public class TestReenterSelfLock {
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();
}
// 主线程每隔1秒换行
for (int i = 0; i < 100; i++) {
SleepTools.second(1);
}
}
public static void main(String[] args) {
TestReenterSelfLock testMyLock = new TestReenterSelfLock();
testMyLock.test();
}
}
Thread-0
Thread-1
Thread-2
Thread-0 ready get lock
Thread-0 already got lock
Thread-0:递归层级:3
Thread-0 ready get lock
Thread-0 already got lock
Thread-0:递归层级:2
Thread-0 ready get lock
Thread-0 already got lock
Thread-0:递归层级:1
Thread-0 ready release lock
Thread-0 already released lock
Thread-0 ready release lock
Thread-0 already released lock
Thread-0 ready release lock
Thread-0 already released lock
Thread-2 ready get lock
Thread-2 already got lock
Thread-2:递归层级:3
Thread-2 ready get lock
Thread-2 already got lock
Thread-2:递归层级:2
Thread-2 ready get lock
Thread-2 already got lock
Thread-2:递归层级:1
Thread-2 ready release lock
Thread-2 already released lock
Thread-2 ready release lock
Thread-2 already released lock
Thread-2 ready release lock
Thread-2 already released lock
Thread-1 ready get lock
Thread-1 already got lock
Thread-1:递归层级:3
Thread-1 ready get lock
Thread-1 already got lock
Thread-1:递归层级:2
Thread-1 ready get lock
Thread-1 already got lock
Thread-1:递归层级:1
Thread-1 ready release lock
Thread-1 already released lock
Thread-1 ready release lock
Thread-1 already released lock
Thread-1 ready release lock
Thread-1 already released lock
公平和非公平锁
公平:每一个线程都放到队列的队尾,挂到最后一起排队
非公平:新进程可以抢占拿锁