一、定义
AbstractQueuedSynchronizer抽象类
是一个用于构建锁,同步器,协作工具类的工具类
有了AQS各种协作工具类都可以很方便的被写出来
二、三个要素
1.state和FIFO队列(下面图解)
1.1 定义
/**
* The synchronization state.
* 对state操作是cas方式,故原子性可以保证
* state可以看成持有锁的数量
*/
private volatile int state;
state各类含义有所不同
FIFO队列node节点(存了被挂起的线程)
1.2 CountDownLatch使用
1.21 构造方法
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
//静态内部类,继承AQS
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//count当成state用
Sync(int count) {
setState(count);
}
...
}
protected final void setState(int newState) {
state = newState;
}
1.22 getCount()
public long getCount() {
return sync.getCount();
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
int getCount() {
return getState();
}
...
}
1.23 countDown()
public void countDown() {
sync.releaseShared(1);
}
这是sync父类AbstractQueuedSynchronizer的方法
public final boolean releaseShared(int arg) {
//使用cas自旋的方式,令牌减为0时候返回true
if (tryReleaseShared(arg)) {
//通过自旋的方式,unpark线程(唤醒队列中线程)
// Unsafe类的 park()作用是将当前调用线程阻塞,unpark()则是将指定线程线程唤醒
doReleaseShared();
return true;
}
return false;
}
sync重写的方法
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
这是sync父类AbstractQueuedSynchronizer的方法
/**
* Release action for shared mode -- signals successor and ensures
* propagation. (Note: For exclusive mode, release just amounts
* to calling unparkSuccessor of head if it needs signal.)
*/
private void doReleaseShared() {
for (;;) {
Node h = head;
//头节点!=尾节点,队列还有节点 --队列的node节点是一个个包装的线程
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
1.24 awit()
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
这是sync父类AbstractQueuedSynchronizer的方法
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//如果令牌(count,state)不为0时
if (tryAcquireShared(arg) < 0)
//
doAcquireSharedInterruptibly(arg);
}
sync重写的方法
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
这是sync父类AbstractQueuedSynchronizer的方法
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
//cas方式添加尾节点
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//parkAndCheckInterrupt往下翻有调用Unsafe类的park方法
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
扩展demo,帮助理解
package aqs.cntdownl;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//一个线程等待多个线程执行
public class CountDownLatchDemo1 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5);
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int count = i + 1;
Runnable runnable = () -> {
try {
Thread.sleep((long) (Math.random() * 1000));
System.out.println("No." + count + "完成了检查");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//取出一个state ... state==0,释放线程
latch.countDown();
}
};
executor.submit(runnable);
}
System.out.println("等待检查完成...");
//state取出,先挂起线程
latch.await();
}
}
//多个线程等待一个线程执行(begin对象),可以做压测 --ps,一对多也在
class CountDownLatchDemo2{
public static void main(String[] args) throws InterruptedException {
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(5);
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int count = i + 1;
Runnable runnable = () -> {
try {
begin.await();
System.out.println("No." + count + "开始跑步...");
Thread.sleep((long) (Math.random()*10000));
System.out.println("No." + count + "...跑步结束");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
end.countDown();
}
};
executor.submit(runnable);
}
System.out.println("裁判员做准备...");
Thread.sleep(5000);
System.out.println("发令枪响...");
begin.countDown();
end.await();
System.out.println("比赛结束...");
}
}
总结:
state --new对象时传入的参数state被获取完,线程统一执行
–单独一个线程去awit,挂起需要执行的线程
–countDown完state,线程开始执行
1.3 Semaphore
1.31 构造方法
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
//设置公平锁
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
Semaphore两个静态内部类,当然也有sync,就不贴了
/**
* NonFair version
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
/**
* Fair version
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (;;) {
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
思路:
两个类比较,差别在tryAcquireShared()方法,这个方法比较核心
1.32 acquire() : void
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
AQS的方法
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
//许可证获取完了,就可以挂起之后的线程了
doAcquireSharedInterruptibly(arg);
}
注意看两个静态内部类 extends Sync
默认的是非公平锁,以此为例
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
//此类把暂时不用的代码删除了
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
在类Sync中
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//获取当前许可证(令牌貌似不合适,改口了)
int available = getState();
//当前拥有的数量 - 想要获取的数量
int remaining = available - acquires;
//如果被值为负数,则不执行后面的cas,如果值>=0,则cas设置下更新后的state并返回,注意这里的state可以为0
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
1.33 tryAcquire() : boolean
public boolean tryAcquire() {
//判断有没有许可证给你这个线程获取
return sync.nonfairTryAcquireShared(1) >= 0;
}
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
1.34 release()
public void release() {
sync.releaseShared(1);
}
AQS方法
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
//看CountDownLatch的release()
doReleaseShared();
return true;
}
return false;
}
Sync方法
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
}
扩展demo帮助理解
package aqs.semphore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
//可用于限流
public class SemaphoreDemo {
public static void main(String[] args) throws InterruptedException {
//获取许可证公平点,每个线程需要许可证的数量不一定一样
Semaphore semaphore=new Semaphore(6,true);
ExecutorService executor = Executors.newFixedThreadPool(50);
for (int i = 0; i < 10; i++) {
Runnable runnable=()->{
try {
semaphore.acquire(1);
System.out.println(Thread.currentThread().getName()+"获取许可证,有许可证1个,为所欲为...");
Thread.sleep((long) (Math.random()*3000));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"...潇洒之后,归还许可证");
semaphore.release(1);
}
};
executor.submit(runnable);
}
for (int i = 0; i < 3; i++) {
Runnable runnable1=()->{
try {
semaphore.acquire(2);
System.out.println(Thread.currentThread().getName()+"获取许可证,有许可证2个,为所欲为...");
Thread.sleep((long) (Math.random()*3000));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"...潇洒之后,归还许可证");
semaphore.release(2);
}
};
//每个线程可能持有不同数量的许可证
executor.submit(runnable1);
}
}
}
总结:
state --许可证
–持有state的线程可以开始执行任务
–一个线程可能持有多个state
–使用完state要归还,获取多少个归还对少个
1.4 ReentrantLock
1.41 构造方法
1.42 lock()
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
//默认的是非公平锁,以此为例
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
//期望0是当前锁未被获取
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
}
public final void acquire(int arg) {
/**
1, 此资源锁被获取了,但不是当前线程
2, addWaiter()设置到等到的队列中去
Node.EXCLUSIVE互斥锁
3, acquireQueued等待有机会就获取锁
*/
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//打断当前线程
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果当前线程已经加锁了
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置重入锁
setState(nextc);
return true;
}
return false;
}
1.43 lockInterruptibly()
1.44 tryLock()
1.45 unlock()
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
//当前线程锁释放完毕才往下走
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
//唤醒队列线程来获取此锁资源
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
//c表示当前线程持有锁的数量(可重入锁)
int c = getState() - releases;
//判断当前线程是不是持有锁的线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
//当前state>0时,直接走这个方法,返回false
setState(c);
return free;
}
写一篇关于锁的博客…
1.5 Condition
1.51 ConditionDemo1
package cn.imooc.aqs.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionDemo1 {
public static void main(String[] args) {
/**
* 1,一个线程挂起,需要另一个线程唤醒
* 2,需要开启lock锁
* 3,等会看源码分析原因
*/
Lock lock=new ReentrantLock();
Condition demo=lock.newCondition();
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+",正在准备工具...");
lock.lock();
try {
demo.await();
System.out.println("await完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"...准备工作已完成");
lock.lock();
try {
demo.signal();
System.out.println("signal完成");
}finally {
lock.unlock();
}
}).start();
}
}
1.52 ConditionDemo2
package cn.imooc.aqs.condition;
import java.util.PriorityQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//经典生产者,消费者问题
public class ConditionDemo2 {
private final int queueSize=10;
private ArrayBlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
private Lock lock=new ReentrantLock();
//生产者 --队列满了不可生产
private Condition notFull = lock.newCondition();
//消费者 --队列为空,没办法消费
private Condition notEmpty = lock.newCondition();
public static void main(String[] args) {
ConditionDemo2 conditionDemo2=new ConditionDemo2();
Consumer consumer=conditionDemo2.new Consumer();
Producer producer=conditionDemo2.new Producer();
consumer.start();
producer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consumer();
}
void consumer(){
while (true){
//注意lock上锁的位置
lock.lock();
try{
while (queue.size()==0){
//如果在此处lock住,
// lock.lock();
System.out.println("队列没有消息可供消费,请等待...");
notEmpty.await();
}
queue.poll();
System.out.println(queue.size()+": 消费了队列一条消息");
notFull.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
producer();
}
void producer(){
while (true){
lock.lock();
try{
while (queue.size()==queueSize){
System.out.println("队列消息已满,请等待消费者消费...");
notFull.await();
}
queue.offer(1);
System.out.println(queue.size()+":生产了一条消息,队列剩余空间:"+(queueSize-queue.size()));
notEmpty.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
}
1.53 await()源码解析 --暂停
Condition接口
void await() throws InterruptedException;
AbstractQueuedSynchronizer抽象类
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
1.54 signalAll()源码解析
1.6 CyclicBarrier
1.61 CyclicBarrierDemo
package cn.imooc.aqs.cyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier=new CyclicBarrier(5,() -> {
System.out.println("所有人到达了集合地点,出发");
});
CyclicBarrierDemo demo=new CyclicBarrierDemo();
for (int i = 0; i < 10; i++) {
new Thread(demo.new CyclicTest(i,cyclicBarrier)).start();
}
}
class CyclicTest implements Runnable{
private int id;
private CyclicBarrier cyclicBarrier;
public CyclicTest(int id, CyclicBarrier cyclicBarrier) {
this.id = id;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println(id+"->正在前往集合地点");
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println(id+"号,到达集合地点");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}