J.U.C下的AQS及相关实现类的应用与解析

AQS

AQS ( Abstract Queued Synchronizer )是一个抽象的队列同步器,通过维护一个共享资源状态( Volatile Int State )和一个先进先出( FIFO )的线程等待队列来实现一个多线程访问共享资源的同步框架。
在这里插入图片描述

AQS 定义了两种资源共享方式:
1.Exclusive:独占,只有一个线程能执行,如ReentrantLock
2.Share:共享,多个线程可以同时执行,如Semaphore、CountDownLatch、CyclicBarrier

重入锁ReentrantLock

定义:一个持有锁的线程,在释放锁之前,如果再次访问加了该同步锁的其他方法,这个线程不需要去争抢锁,只需要记录其重入次数。默认使用sync的不公平锁NonfairSync实现。
实现图解
在这里插入图片描述
这里需要注意的是,由于ReentranLock默认基于NoFairSync实现,所以在线程队列中的线程被唤醒时,不会直接获取到锁,而是需要和外部进入的新线程去争抢锁。当然,新的线程如果没有抢到锁,也会进入线程队列等待顺序唤醒。

倒计时 CountDownLatch

定义:允许一个或多个线程一直等待,直到其他线程的操作执行完毕在执行。
初始化源码

 public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

由其初始化方式,可以看出,countDownLatch的本质是直接给AQS的state赋值,后面必须要执行对应个数的释放锁操作,才能使相应的线程继续操作。
使用图解
在这里插入图片描述

当然,如果执行的线程次数不够时,会导致阻塞,无法进行唤醒。

限流Semaphore

定义:译为信号量,可以控制同时访问的线程个数,通过acquire()获得一个许可,如果没有就进入等待队列;通过release释放一个许可,唤醒全部等待的线程去抢夺锁。类似于限流;
在这里插入图片描述

CylicBarrier(可循环使用的屏障)

定义:让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续工作。其功能类似于CountDownLatch;不同的是,CountDownLatch是基于
使用场景:存在需要所有子任务都完成后才执行主任务。
当线程数与parties(循环次数)不一致时,所有线程都会被阻塞;解决方法
①设定await(timeout),超时退出等待
②通过cyclicBarrier.rest重置计数器,抛出异常进行处理。
实现原理:CylicBarrier是基于AQS中的ReentrantLock和Condition实现。值得注意的是,在执行barrierAction时,调用的是run()方法而不是start。
start() 方法用于启动或开始执行新创建的线程。当调用 start() 方法时,会创建一个新线程,并且这个新创建的线程会执行保存在 run() 方法中的任务。只能调用一次 start() 方法。
run() 方法用于启动或开始执行同一个线程。当调用 run() 方法时,不会像 start() 方法那样创建新线程。该方法由当前线程执行。可以多次调用。
在这里插入图片描述

独占式和共享式锁唤醒线程队列的不同

独占式:只唤醒head下的nextNode

    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

共享式:通过自旋锁,唤醒队列中除了head以外全部的Node(因为head实际上只做一个标志,并没有关联实际线程)

private void doReleaseShared() {
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {//通过unparkSuccessor唤醒节点,直到h=head
                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;
        }
    }

Condition条件

  • Condition是一个多线程协调通信的工具类,可以让某些线程一起等待某个条件,当条件被满足时,线程才会被唤醒。其原理是通过AQS等待队列及condition队列实现等待唤醒
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值