多线程(十二、AQS原理-CountDownLatch基于AQS的共享实现)

1、CountDownLatch介绍

1.1 CountDownLatch的使用,请参考文章 多线程(七、同步计数器-CountDownLatch

2、案例分析

2.1 说明:

1、Thread-1执行await,等待主线程放行;
2、Thread-2执行await,等待主线程放行;
3、主线程执行countDown()放行。

3、源码分析

3.1 CountDownLatch的构造函数和如何使用AQS的同步状态:


1、CountDownLatch的初始计数器就是直接设置AQS的同步状态值state
2、countDown就是对state执行减1
3、当state为0的时候,放行。

3.2 Thread-1调用await

3.2.1 就是调用AQS的acquireSharedInterruptibly方法

3.2.2 tryAcquireShared的实现要比ReentrantLock简单很多

只要state是0,则所有获取资源的申请都会成功,这就是共享锁的含义。

3.2.3 如果主线程不放行,state不等于0,,申请失败,会执行doAcquireSharedInterruptibly

此时,自旋获取一次也会失败,会进行阻塞,进入【等待队列】

3.3 Thread-2调用await,结果同上,Thread-2也进入【等待队列】

3.4 主线程放行countDown()

3.4.1 countDown()

tryReleaseShared方法

然后执行doReleaseShared,唤醒Thread-1

Thread-1被唤醒后,从阻塞的地方继续执行,重新获取资源,此时state=0,则会获取成功

然后执行:setHeadAndPropagate方法把ThreadA结点变为头结点,并根据传播状态判断是否要唤醒并释放后继结点

private void setHeadAndPropagate(Node node, int propagate) {
        Node h = head; // Record old head for check below
        setHead(node);//设置当前节点为头节点

        if (propagate > 0 || h == null || h.waitStatus < 0 ||
                (h = head) == null || h.waitStatus < 0) {
            Node s = node.next;
            if (s == null || s.isShared()) //后继节点如果是共享的,则依次唤醒后继节点,这就是共享的原理
                doReleaseShared();
        }
    }

3.5 Thread-1会继续唤醒Thread-2,Thread-2继续执行,会继续唤醒后续共享节点,此时后面没有节点了,程序完成。

原文地址:https://blog.51cto.com/janephp/2410908

时间: 2024-10-09 04:16:04

多线程(十二、AQS原理-CountDownLatch基于AQS的共享实现)的相关文章

聊聊高并发(三十二)实现一个基于链表的无锁Set集合

Set表示一种没有反复元素的集合类,在JDK里面有HashSet的实现,底层是基于HashMap来实现的.这里实现一个简化版本号的Set,有下面约束: 1. 基于链表实现.链表节点依照对象的hashCode()顺序由小到大从Head到Tail排列. 2. 如果对象的hashCode()是唯一的.这个如果实际上是不成立的,这里为了简化实现做这个如果.实际情况是HashCode是基于对象地址进行的一次Hash操作.目的是把对象依据Hash散开.所以可能有多个对象地址相应到一个HashCode.也就是

2.5星|刘慈欣等《十二个明天》:作为小说比较失败,读起来不够吸引人

十二个明天(此书单独装订书脊与封皮不粘连) 前言是编者写的,说“十二个明天”是基于科技发展和应用科学研究的硬科幻专栏.作者的意思应该是说这是<麻省理工科技评论>的一个专栏,但是看中文有点含糊,可能是译者的问题. 全书有十一篇科幻小说和一篇科幻小说作家小传,还有十二篇点评.第一篇小说是刘慈欣的作品. 看了前两篇小说和第三篇的一小半决定放弃,看了看后面的点评,大致了解了小说的主要情节. 看过的两篇半小说中,作为小说比较失败,读起来不够吸引人,对我来说就不如去读评论了解作者想基于哪些科技去做幻想.

多线程(十、AQS原理-ReentrantLock实现)

ReentrantLock介绍 ReentrantLock 基于AQS实现了公平和非公平的独占锁功能. ReentrantLock定义AQS的同步状态(synchronization state)如下: State为0表示锁可用:为1表示被占用:为N表示锁重入的次数,是独占资源. ReentrantLock实现公平锁原理 案例代码如下: 1.启动文件 public class Main { public static void main(String[] args) throws ParseEx

多线程(九、AQS原理-简介)

AQS介绍 AQS是一个抽象类,提供了一套通用的控制同步状态,线程阻塞/唤醒,等待队列管理的操作. 平时用的ReentrantLock,CountDownLatch,Semaphore(信号量)都是基于AQS提供API来实现的,他们的不同之处就是对于AQS内部的同步状态(synchronization state,int类型)操作不同,来实现的功能不同. AQS基于同步状态(synchronization state)主要解决了3个问题: 1.资源的访问是共享的还是独占的,比方说Reentran

并发编程(三):从AQS到CountDownLatch与ReentrantLock

一.目录 1.AQS简要分析 2.谈CountDownLatch 3.谈ReentrantLock 4.谈消费者与生产者模式(notfiyAll/wait.signAll/await.condition) 二.AQS简要分析 问题:AQS是什么?有什么用? AQS是什么? 字面上看,它被称为抽象队列式的同步器(AbstractQueuedSynchronizer).简单说,它就是一个同步队列容器. AQS有什么用? 为什么会产生ArrayList.LinkedList.HashMap这些容器?它

AQS 原理以及 AQS 同步组件总结

1 AQS 简单介绍 AQS 的全称为(AbstractQueuedSynchronizer),这个类在 java.util.concurrent.locks 包下面. AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等皆是基于 AQS 的.当然,我们自己也能利用 AQ

AQS原理分析

一,AQS原理 lock最常用的类就是ReentrantLock,其底层实现使用的是AbstractQueuedSynchronizer(AQS) 简单来说AQS会把所有的请求线程构成一个CLH队列,当一个线程执行完毕(lock.unlock())时会激活自己的后继节点,但正在执行的线程并不在队列中,而那些等待执行的线程全部处于阻塞状态,经过调查线程的显式阻塞是通过调用LockSupport.park()完成,而LockSupport.park()则调用sun.misc.Unsafe.park(

Java 多线程与并发(六):AQS

我们前面几张提到过,JUC 这个包里面的工具类的底层就是使用 CAS 和 volatile 来保证线程安全的,整个 JUC 包里面的类都是基于它们构建的.今天我们介绍一个非常重要的同步器,这个类是 JDK 在 CAS 和 volatile 的基础上为我们提供的一个同步工具类. 背景 AbstractQueuedSynchronizer,JDK 1.5 引入了 JUC 包,这个包提供了一些列支持并发的组件,这些组件是一些列同步器,他们主要完成以下功能: 内部状态的管理和更新,比如表示一个锁的状态是

基于AQS的锁

锁分为独占锁和共享锁,它们的主要实现都是依靠AbstractQueuedSynchronizer,这个类只提供一系列公共的方法,让子类来调用.基于我了解不深,从这个类的属性,方法,和独占锁的获取方式去了解这个类. AbstractQueuedSynchronizer的主要属性和方法: 属性/方法 含    义 Thread exclusiveOwnerThread 这个是AQS父类AbstractOwnableSynchronizer的属性,表示独占模式同步器的当前拥有者 Node 上面已经介绍