AQS解读及AQS相关实现类

AQS解读及相关AQS实现类

1. AQS概述

简述:AQS全称AbstractQueuedSynchronizer,即抽象队列同步器。AQS是用来构建锁或者其他同步组件的基础框架,它使用一个整型的volatile变量state来维护同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。AQS为一系列同步器依赖于一个单独的原子变量state的同步器提供了一个非常有用的基础。

AQS的设计是基于模板方法模式设计的,子类通过继承AQS并实现它的抽象模板方法来管理同步状态,而这些模板方法内部就是真正管理同步状态的地方(主要有tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared等)。

AQS既可以支持独占锁地,也支持共享锁,这样就可以方便实现不同类型的同步组件如ReentrantLock、ReentrantReadWriteLock和CountDownLatch等。

AQS类使用单个int(32位)来保存同步状态,并暴露出getState、setState以及compareAndSet操作来读取和更新这个同步状态。其中属性state被声明为volatile,并且通过使用CAS指令来实现compareAndSetState,使得当且仅当同步状态拥有一个一致的期望值的时候,才会被原子地设置成新值,这样就达到了同步状态的原子性管理,确保了同步状态的原子性、可见性和有序性。

AQS简单推导流程:
1.根据ReentrantLock、ReentrantReadWriteLock实现推导,深入理解JAVA中的锁那节,讲到了ReentrantLock、ReentrantReadWriteLock的实现原理,他们都有共同的特性,owner(锁持有者)、writecount(重入次数)、waiters(等待队列),简单的AQS即是提出公共的代码,提供必要的实现类,实现不同的锁功能。
2.先看自己实现的ReentrantLock、ReentrantReadWriteLock的代码
ReentrantLock:

package com.study.lock.locks1;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

public class JamesReentrantLock implements Lock {


    //标记重入次数的count值
    AtomicInteger count = new AtomicInteger(0);

    //锁的拥有者
    AtomicReference<Thread> owner = new AtomicReference<>();

    //等待队列
    private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();


    @Override
    public boolean tryLock() {
        //判断count是否为0,若count!=0,说明锁被占用
        int ct = count.get();
        if (ct !=0 ){
            //判断锁是否被当前线程占用,若被当前线程占用,做重入操作,count+=1
            if (owner.get() == Thread.currentThread()){
                count.set(ct + 1);
                return true;
            }else{
                //若不是当前线程占用,互斥,抢锁失败,return false
                return false;
            }
        }else{
            //若count=0, 说明锁未被占用,通过CAS(0,1) 来抢锁
            if (count.compareAndSet(ct, ct +1)){
                //若抢锁成功,设置owner为当前线程的引用
                owner.set(Thread.currentThread());
                return true;
            }else{
                //CAS操作失败,说明情锁失败 返回false
                return false;
            }
        }
    }

    @Override
    public void lock() {
        //尝试抢锁
        if (!tryLock()){
            //如果失败,进入等待队列
            waiters.offer(Thread.currentThread());

            //自旋
            for (;;){
                //判断是否是队列头部,如果是
                Thread head = waiters.peek();
                if (head == Thread.currentThread()){
                    //再次尝试抢锁
                    if (!tryLock()){
                        //若抢锁失败,挂起线程,继续等待
                        LockSupport.park();
                    }else{
                        //若成功,就出队列
                        waiters.poll();
                        return;
                    }
                }else{
                    //如果不是,就挂起线程
                    LockSupport.park();
                }
            }
        }
    }

    @Override
    public void unlock() {
        if (tryUnlock()){
            Thread th = waiters.peek();
            if (th !=null){
                LockSupport.unpark(th);
            }
        }
    }


    public boolean tryUnlock(){
        //判断,是否是当前线程占有锁,若不是,抛异常
        if (owner.get() != Thread.currentThread()){
            throw new IllegalMonitorStateException();
        }else{
            //如果是,就将count-1  若count变为0 ,则解锁成功
            int ct = count.get();
            int nextc = ct-1;
            count.set(nextc);

            //判断count值是否为0
            if (nextc == 0){
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            }else{
                return false;
            }
        }
    }



    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

ReentrantReadWriteLock:

package com.study.lock.locks1;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;


public class JamesReadWriteLock {
    volatile AtomicInteger readCount = new AtomicInteger(0);
    AtomicInteger writeCount = new AtomicInteger(0);

    //独占锁 拥有者
    AtomicReference<Thread> owner = new AtomicReference<>();

    //等待队列
    public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<WaitNode>();
    class WaitNode{
        int type = 0;   //0 为想获取独占锁的线程,  1为想获取共享锁的线程
        Thread thread = null;
        int arg = 0;

        public WaitNode(Thread thread, int type, int arg){
            this.thread = thread;
            this.type = type;
            this.arg = arg;
        }
    }


    //获取独占锁
    public void lock() {
        int arg = 1;
        //尝试获取独占锁,若成功,退出方法,    若失败...
        if (!tryLock(arg)){
            //标记为独占锁
            WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
            waiters.offer(waitNode);    //进入等待队列

            //循环尝试拿锁
            for(;;){
                //若队列头部是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (!tryLock(arg)){      //再次尝试获取 独占锁
                        LockSupport.park();     //若失败,挂起线程
                    } else{     //若成功获取
                        waiters.poll();     //  将当前线程从队列头部移除
                        return;         //并退出方法
                    }
                }else{  //若不是队列头部元素
                    LockSupport.park();     //将当前线程挂起
                }
            }
        }
    }

    //释放独占锁
    public boolean unlock() {
        int arg = 1;

        //尝试释放独占锁 若失败返回true,若失败...
        if(tryUnlock(arg)){
            WaitNode next = waiters.peek(); //取出队列头部的元素
            if (next !=null){
                Thread th = next.thread;
                LockSupport.unpark(th);     //唤醒队列头部的线程
            }
            return true;                //返回true
        }
        return false;
    }

    //尝试获取独占锁
    public boolean tryLock(int acquires) {
        //如果read count !=0 返回false
        if (readCount.get() !=0)
            return false;

        int wct = writeCount.get();     //拿到 独占锁 当前状态

        if (wct==0){
            if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                return true;
            }
        }else if (owner.get() == Thread.currentThread()){
            writeCount.set(wct + acquires);     //修改count值
            return true;
        }

        return false;
    }

    //尝试释放独占锁
    public boolean tryUnlock(int releases) {
        //若当前线程没有 持有独占锁
        if(owner.get()!= Thread.currentThread()){
            throw new IllegalMonitorStateException();       //抛IllegalMonitorStateException
        }

        int wc= writeCount.get();
        int nextc = wc - releases;      //计算 独占锁剩余占用
        writeCount.set(nextc);      //不管是否完全释放,都更新count值

        if (nextc==0){  //是否完全释放
            owner.compareAndSet(Thread.currentThread(), null);
            return true;
        }else{
            return false;
        }

    }

    //获取共享锁
    public void lockShared() {
        int arg = 1;

        if (tryLockShared(arg) < 0){    //如果tryAcquireShare失败
            //将当前进程放入队列
            WaitNode node = new WaitNode(Thread.currentThread(), 1, arg);
            waiters.offer(node);  //加入队列

            for (;;){
                //若队列头部的元素是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (tryLockShared(arg) >=0){    //尝试获取共享锁,  若成功
                        waiters.poll();      //将当前线程从队列中移除

                        WaitNode next = waiters.peek();
                        if (next!=null && next.type==1){    //如果下一个线程也是等待共享锁
                            LockSupport.unpark(next.thread);    //将其唤醒
                        }
                        return;     //退出方法
                    }else{                      //若尝试失败
                        LockSupport.park();     //挂起线程
                    }
                }else{  //若不是头部元素
                    LockSupport.park();
                }

            }
        }
    }

    //解锁共享锁
    public boolean unLockShared() {
        int arg = 1;

        if (tryUnLockShared(arg)){     //当read count变为0,才叫release share成功
            WaitNode next = waiters.peek();
            if (next!=null){
                LockSupport.unpark(next.thread);
            }
            return true;
        }
        return false;
    }

    //尝试获取共享锁
    public int tryLockShared(int acquires) {
        for (;;){
            if (writeCount.get()!=0 &&
                    owner.get() != Thread.currentThread())
                return -1;
            int rct = readCount.get();
            if (readCount.compareAndSet(rct, rct + acquires)){
                return 1;
            }
        }
    }

    //尝试解锁共享锁
    public boolean tryUnLockShared(int releases) {
        for(;;){
            int rc = readCount.get();
            int nextc = rc - releases;
            if (readCount.compareAndSet(rc, nextc)){
                return nextc==0;
            }
        }
    }
}
  1. 提出公共代码后的相关代码
    公共代码类
package com.study.lock.locks5;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

public class JamesAQS {
    AtomicInteger readCount = new AtomicInteger(0);
    AtomicInteger writeCount = new AtomicInteger(0);

    //独占锁 拥有者
    AtomicReference<Thread> owner = new AtomicReference<>();

    //等待队列
    public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<WaitNode>();
    class WaitNode{
        int type = 0;   //0 为想获取独占锁的线程,  1为想获取共享锁的线程
        Thread thread = null;
        int arg = 0;

        public WaitNode(Thread thread, int type, int arg){
            this.thread = thread;
            this.type = type;
            this.arg = arg;
        }
    }


    //获取独占锁
    public void lock() {
        int arg = 1;
        //尝试获取独占锁,若成功,退出方法,    若失败...
        if (!tryLock(arg)){
            //标记为独占锁
            WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
            waiters.offer(waitNode);    //进入等待队列

            //循环尝试拿锁
            for(;;){
                //若队列头部是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (!tryLock(arg)){      //再次尝试获取 独占锁
                        LockSupport.park();     //若失败,挂起线程
                    } else{     //若成功获取
                        waiters.poll();     //  将当前线程从队列头部移除
                        return;         //并退出方法
                    }
                }else{  //若不是队列头部元素
                    LockSupport.park();     //将当前线程挂起
                }
            }
        }
    }

    //释放独占锁
    public boolean unlock() {
        int arg = 1;

        //尝试释放独占锁 若失败返回true,若失败...
        if(tryUnlock(arg)){
            WaitNode next = waiters.peek(); //取出队列头部的元素
            if (next !=null){
                Thread th = next.thread;
                LockSupport.unpark(th);     //唤醒队列头部的线程
            }
            return true;                //返回true
        }
        return false;
    }

    //获取共享锁
    public void lockShared() {
        int arg = 1;

        if (tryLockShared(arg) < 0){    //如果tryAcquireShare失败
            //将当前进程放入队列
            WaitNode node = new WaitNode(Thread.currentThread(), 1, arg);
            waiters.offer(node);  //加入队列

            for (;;){
                //若队列头部的元素是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (tryLockShared(arg) >=0){    //尝试获取共享锁,  若成功
                        waiters.poll();      //将当前线程从队列中移除

                        WaitNode next = waiters.peek();
                        if (next!=null && next.type==1){    //如果下一个线程也是等待共享锁
                            LockSupport.unpark(next.thread);    //将其唤醒
                        }
                        return;     //退出方法
                    }else{                      //若尝试失败
                        LockSupport.park();     //挂起线程
                    }
                }else{  //若不是头部元素
                    LockSupport.park();
                }

            }
        }
    }

    //解锁共享锁
    public boolean unLockShared() {
        int arg = 1;

        if (tryUnLockShared(arg)){     //当read count变为0,才叫release share成功
            WaitNode next = waiters.peek();
            if (next!=null){
                LockSupport.unpark(next.thread);
            }
            return true;
        }
        return false;
    }




    //尝试获取独占锁
    public boolean tryLock(int acquires) {
        throw new UnsupportedOperationException();
    }

    //尝试释放独占锁
    public boolean tryUnlock(int releases) {
        throw new UnsupportedOperationException();
    }

    //尝试获取共享锁
    public int tryLockShared(int acquires) {
        throw new UnsupportedOperationException();
    }

    //尝试解锁共享锁
    public boolean tryUnLockShared(int releases) {
        throw new UnsupportedOperationException();
    }
}

改写后的ReadWriteLock:

package com.study.lock.locks5;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

public class JamesReadWriteLock implements ReadWriteLock {
    JamesAQS mask = new JamesAQS(){
        //尝试获取独占锁
        public boolean tryLock(int acquires) {
            //如果read count !=0 返回false
            if (readCount.get() !=0)
                return false;

            int wct = writeCount.get();     //拿到 独占锁 当前状态

            if (wct==0){
                if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }

            return false;
        }

        //尝试释放独占锁
        public boolean tryUnlock(int releases) {
            //若当前线程没有 持有独占锁
            if(owner.get()!= Thread.currentThread()){
                throw new IllegalMonitorStateException();       //抛IllegalMonitorStateException
            }

            int wc= writeCount.get();
            int nextc = wc - releases;      //计算 独占锁剩余占用
            writeCount.set(nextc);      //不管是否完全释放,都更新count值

            if (nextc==0){  //是否完全释放
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            }else{
                return false;
            }

        }


        //尝试获取共享锁
        public int tryLockShared(int acquires) {
            for (;;){
                if (writeCount.get()!=0 &&
                        owner.get() != Thread.currentThread())
                    return -1;

                int rct = readCount.get();
                if (readCount.compareAndSet(rct, rct + acquires)){
                    return 1;
                }
            }
        }

        //尝试解锁共享锁
        public boolean tryUnLockShared(int releases) {
            for(;;){
                int rc = readCount.get();
                int nextc = rc - releases;
                if (readCount.compareAndSet(rc, nextc)){
                    return nextc==0;
                }
            }
        }

    };


    @Override
    public Lock readLock() {
        return new Lock() {
            @Override
            public void lock() {
                mask.lockShared();
            }

            @Override
            public void lockInterruptibly() throws InterruptedException {

            }

            @Override
            public boolean tryLock() {
                return mask.tryLockShared(1) == 1;
            }

            @Override
            public void unlock() {
                mask.unLockShared();
            }

            @Override
            public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
                return false;
            }



            @Override
            public Condition newCondition() {
                return null;
            }
        };
    }

    @Override
    public Lock writeLock() {
        return new Lock() {
            @Override
            public void lock() {
                mask.lock();
            }


            @Override
            public boolean tryLock() {
                return mask.tryLock(1);
            }


            @Override
            public void unlock() {
                mask.unlock();
            }

            @Override
            public void lockInterruptibly() throws InterruptedException {

            }



            @Override
            public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
                return false;
            }



            @Override
            public Condition newCondition() {
                return null;
            }
        };
    }
}

改写后的Reentrantlock:

package com.study.lock.locks5;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class JamesReentrantLock implements Lock {

    private boolean isFair;

    public JamesReentrantLock(boolean isFair){
        this.isFair = isFair;
    }

    JamesAQS mask = new JamesAQS(){
        public boolean tryLock(int acquires){
            if (isFair){
                return tryFairLock(acquires);
            }else{
                return tryNonFairLock(acquires);
            }
        }

        //尝试获取独占锁
        public boolean tryNonFairLock(int acquires) {
            //如果read count !=0 返回false
            if (readCount.get() !=0)
                return false;

            int wct = writeCount.get();     //拿到 独占锁 当前状态

            if (wct==0){
                if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }

            return false;
        }

        public boolean tryFairLock(int acquires){
            //如果read count !=0 返回false
            if (readCount.get() !=0)
                return false;

            int wct = writeCount.get();     //拿到 独占锁 当前状态

            if (wct==0){
                JamesAQS.WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()&&
                        writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }

            return false;
        }


        //尝试释放独占锁
        public boolean tryUnlock(int releases) {
            //若当前线程没有 持有独占锁
            if(owner.get()!= Thread.currentThread()){
                throw new IllegalMonitorStateException();       //抛IllegalMonitorStateException
            }

            int wc= writeCount.get();
            int nextc = wc - releases;      //计算 独占锁剩余占用
            writeCount.set(nextc);      //不管是否完全释放,都更新count值

            if (nextc==0){  //是否完全释放
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            }else{
                return false;
            }

        }

    };

    public void lock(){
        mask.lock();
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }


    @Override
    public Condition newCondition() {
        return null;
    }
    @Override
    public boolean tryLock(){
        return mask.tryLock(1);
    }
    @Override
    public void unlock(){
        mask.unlock();
    }
    @Override
    public void lockInterruptibly() throws InterruptedException {

    }
}
  1. 原生的AQS提供的主要实现方法
    在这里插入图片描述
  2. AQS源码中的主要字段
// 同步队列的head节点, 延迟初始化,除了初始化,只能通过setHead方法修改
// 如果head存在,waitStatus一定是CANCELLED
private transient volatile Node head;
// 同步队列的tail节点,延迟初始化,只能通过enq方法修改
private transient volatile Node tail;
// 同步状态
private volatile int state;
// 支持CAS
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;

6.AQS源码中的主要方法

protected final int getState() {
        return state;
    }

    protected final void setState(int newState) {
        state = newState;
    }

    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    // 钩子方法,独占式获取同步状态, 需要子类实现,实现此方法需要查询当前同步状态并     
    // 判断同步状态是否符合预期,然后再CAS设置同步状态
    // 返回值true代表获取成功,false代表获取失败
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    // 钩子方法,独占式释放同步状态,需要子类实现,
    // 等待获取同步状态的线程将有机会获取同步状态
    // 返回值true代表获取成功,false代表获取失败
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    // 钩子方法,共享式获取同步状态,需要子类实现,
    // 返回值负数代表获取失败、0代表获取成功但没有剩余资源、
    // 正数代表获取成功,还有剩余资源
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

    // 钩子方法,共享式释放同步状态,需要子类实现
    // 返回值负数代表获取失败、0代表获取成功但没有剩余资源、
    // 正数代表获取成功,还有剩余资源
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

    // 模板方法,独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,
    // 否则会进入同步队列等待,此方法会调用子类重写的tryAcquire方法
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    // 模板方法,独占式的释放同步状态,该方法会在释放同步状态后,
    // 将同步队列中的第一个节点包含的线程唤醒
    // 此方法会调用子类重写的tryRelease方法
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    // 模板方法,共享式的获取同步状态,如果当前系统未获取到同步状态,
    // 将会进入同步队列等待,同一时刻可以有多个线程获取到同步状态
    // 此方法会调用子类重写的tryAcquireShared方法
    public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }


    // 模板方法,共享式的释放同步状态
    // 此方法会调用子类重写的tryReleaseShared方法
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

    // 用于将当前线程加入到等待队列的队尾,并返回当前线程所在的结点
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;    // 尝试将Node放到队尾
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

    //初始化或自旋CAS直到入队成功
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

2. AQS实现CountDownLatch

简述:CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。主要常用的方法countDown()方法以及await())方法。
基于AQS实现CountDownLatch

public class MyCountDownLatch {

  private Sync sync;

  public MyCountDownLatch(int count) {
    sync = new Sync(count);
  }

  public void countDown() {
    sync.releaseShared(1);
  }

  public void await() {
    sync.acquireShared(1);
  }

  class Sync extends AbstractQueuedSynchronizer {
    public Sync(int count) {
      setState(count);
    }

    @Override
    protected int tryAcquireShared(int arg) {
      // 只有当state变为0时,加锁成功
      return getState() == 0 ? 1 : -1;
    }

    @Override
    protected boolean tryReleaseShared(int arg) {
      for (; ; ) {
        int c = getState();
        if (c == 0) return false;
        int nextc = c - 1;
        // 用CAS操作,讲count减一
        if (compareAndSetState(c, nextc)) {
          // 当state=0时,释放锁成功,返回true
          return nextc == 0;
        }
      }
    }
  }
}

// 测试
public class MyCountDownLatchTest {
  /*
  每隔1s开启一个线程,共开启6个线程
  若希望6个线程 同时 执行某一操作
  可以用CountDownLatch实现
   */
  public static void test01() throws InterruptedException {
    MyCountDownLatch ctl = new MyCountDownLatch(6);

    for (int i = 0; i < 6; i++) {
      new Thread() {
        @Override
        public void run() {
          ctl.countDown();
          ctl.await();
          System.out.println("here I am...");
        }
      }.start();
      Thread.sleep(1000L);
    }
  }

  /*
  开启6个线程,main线程希望6个线程都执行完某个操作后,才执行某个操作
  可以用CountDownLatch来实现
   */
  public static void test02() throws InterruptedException {
    MyCountDownLatch ctl = new MyCountDownLatch(6);

    for (int i = 0; i < 6; i++) {
      new Thread() {
        @Override
        public void run() {
          System.out.println("after print...");
          ctl.countDown();
        }
      }.start();
      Thread.sleep(1000L);
    }

    ctl.await();
    System.out.println("main thread do something ...");
  }

  public static void main(String args[]) throws InterruptedException {
    test01();
  }
}

3. AQS实现Semaphore

在这里插入图片描述

4. AQS实现CyclicBarrier

在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值