AQS部分源码学习

一、定义

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();
            }
        }

    }

}

1.62 构造方法
1.63 await()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码style

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值