Java中的阻塞队列(3)同步计数器

简介: 9、同步计数器 CountDownLatch    这是一个同步的辅助类,实现原理为AbstractQueuedSynchronizer抽象队列化同步器图9-1    方法介绍:        1、CountDownLatch(in...

9、同步计数器 CountDownLatch

    这是一个同步的辅助类,实现原理为AbstractQueuedSynchronizer抽象队列化同步器

img_74d435bbedd7ec220def21831331326d.png
图9-1

    方法介绍:

        1、CountDownLatch(int count):构造,并给定计数初始化

        2、await():当前线程在锁存器倒计数到零之前一直等待,除非线程被中断

        3、await(long, TimeUnit):当前线程在锁存器倒计数到零之前一直等待,除非线程被中断或者超出指定时间

        4、countDown():计数减一

        5、getCount():获取当前计数

    至于例子,就通过之前写过的并发单元测试历程就可以

img_3a7541a9b742f625c769b0ef73c2a52c.png
图9-2

    至于实现原理,我们看源码会发现,其实CountDownLatch也是调用了一个AbstractQueuedSynchronizer抽象队列化同步器

10、AbstractQueuedSynchronizer抽象队列化同步器

    这是一个java.util.concurrent的核心组件之一,提供了一个基于FIFO的队列,用于构建锁或者其他相关同步装置的基础框架

    首先看继承结构如图10-1

img_f70a75b881d09306079eb12d45d81d67.png
图10-1

这个继承结构是非常简单的,但是里面包含的方法就 emmmmmmm。。。有点多了,而且这是一个抽象类,但是里面却找不到任何一个抽象方法,想要使用就需要继承这个类才行,AbstractQueuedSynchronizer分为两种模式,排他模式和共享模式,也可以两个模式共存,排他模式时其他线程试图获取该锁将无法取得成功,共享模式则可以同时成功。

    其中的方法子类可以适当的重新定义:

        1、tryAcquire(int)、tryRelease(int):试图在排他模式下获取/销毁对象状态

        2、tryAcquireShared(int)、tryReleaseShared(int):试图在排他模式下获取/销毁对象状态

        3、isHeldExclusively():如果对于当前正在调用的线程,同步是以排他方式进行的,则返回true,判断当前正在执行的线程是否以排他模式进行的

        4、getState()、setState(int)、compareAndSetState(int, int):通过这种方式来改变同步状态

    我们这边提取一个官方的demo,加以说明一下

img_4d35a9982d6f782024c9aabe5699a6ee.png
img_0be67706809d9d3ca814ed91973f76ce.png
img_32da6dafc3d81c1bb9325cc7d9fa9586.png

        以下为Lock对象的实现方法

img_77c951a09e326b682eec2539ad3c6431.png
img_cec46d47f346e4e794915faa6fedf9b8.png
普通重入锁的执行过程

11、同步计数器Semaphore:

    这个其实就是维护了一个许可集合,其实就是在高并发下,允许几个线程同时运行,其余线程放入队列,具体的应用场景就是线程池,这个放在后面说明。

    实现原理其实也很简单,底层也是通过AQS的方式,

12、同步计数器CyclicBarrier

    这个需要对比着CountDownLatch来看

    CountDownLatch:一个线程(或者多个线程),等待另外n个线程完成某个事情之后才能执行

    CyclicBarrier:n个线程互相等待,任何一个线程完成之前,其他的线程都必须等待

    来看一个例子

img_5644124b9a2486d054932f1ed63683c8.png
img_778afe723da6f6ca1d30c4e504032c94.png
img_4b04be275b1fa0ee8e5161f9364976f3.png

    可以看到,三个子线程先执行,一直到三个线程都await的时候,主线程开始执行,主线程执行完毕之后,三个线程开始执行await后面的任务。

    至于源码的解读。。。。。。。还是算了吧。。。

相关文章
|
1月前
|
Java 云计算
Java多线程编程中的同步与互斥机制探析
在当今软件开发领域,多线程编程是一项至关重要的技能。本文将深入探讨Java中的同步与互斥机制,分析其在多线程环境下的应用及实现原理,帮助读者更好地理解并运用这一关键技术。
23 4
|
3月前
|
存储 设计模式 安全
Java 编程问题:十、并发-线程池、可调用对象和同步器2
Java 编程问题:十、并发-线程池、可调用对象和同步器
33 0
|
3月前
|
缓存 安全 Java
Java 编程问题:十、并发-线程池、可调用对象和同步器1
Java 编程问题:十、并发-线程池、可调用对象和同步器
44 0
|
6天前
|
存储 缓存 安全
Java并发基础之互斥同步、非阻塞同步、指令重排与volatile
在Java中,多线程编程常常涉及到共享数据的访问,这时候就需要考虑线程安全问题。Java提供了多种机制来实现线程安全,其中包括互斥同步(Mutex Synchronization)、非阻塞同步(Non-blocking Synchronization)、以及volatile关键字等。 互斥同步(Mutex Synchronization) 互斥同步是一种基本的同步手段,它要求在任何时刻,只有一个线程可以执行某个方法或某个代码块,其他线程必须等待。Java中的synchronized关键字就是实现互斥同步的常用手段。当一个线程进入一个synchronized方法或代码块时,它需要先获得锁,如果
22 0
|
23天前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解08-阻塞队列之LinkedBlockingDeque
**摘要:** 本文分析了Java中的LinkedBlockingDeque,它是一个基于链表实现的双端阻塞队列,具有并发安全性。LinkedBlockingDeque可以作为有界队列使用,容量由构造函数指定,默认为Integer.MAX_VALUE。队列操作包括在头部和尾部的插入与删除,这些操作由锁和Condition来保证线程安全。例如,`linkFirst()`和`linkLast()`用于在队首和队尾插入元素,而`unlinkFirst()`和`unlinkLast()`则用于删除首尾元素。队列的插入和删除方法根据队列是否满或空,可能会阻塞或唤醒等待的线程,这些操作通过`notFul
44 5
|
23天前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解07-阻塞队列之LinkedTransferQueue
`LinkedTransferQueue`是一个基于链表结构的无界并发队列,实现了`TransferQueue`接口,它使用预占模式来协调生产者和消费者的交互。队列中的元素分为数据节点(isData为true)和请求节点(isData为false)。在不同情况下,队列提供四种操作模式:NOW(立即返回,不阻塞),ASYNC(异步,不阻塞,但后续线程可能阻塞),SYNC(同步,阻塞直到匹配),TIMED(超时等待,可能返回)。 `xfer`方法是队列的核心,它处理元素的转移过程。方法内部通过循环和CAS(Compare And Swap)操作来确保线程安全,同时避免锁的使用以提高性能。当找到匹
35 5
|
23天前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解04-阻塞队列之PriorityBlockingQueue原理及扩容机制详解
1. **继承实现图关系**: - `PriorityBlockingQueue`实现了`BlockingQueue`接口,提供了线程安全的队列操作。 - 内部基于优先级堆(小顶堆或大顶堆)的数据结构实现,可以保证元素按照优先级顺序出队。 2. **底层数据存储结构**: - 默认容量是11,存储数据的数组会在需要时动态扩容。 - 数组长度总是2的幂,以满足堆的性质。 3. **构造器**: - 无参构造器创建一个默认容量的队列,元素需要实现`Comparable`接口。 - 指定容量构造器允许设置初始容量,但不指定排序规则。 - 可指定容量和比较
42 2
|
23天前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解03-阻塞队列之LinkedBlockingQueue
LinkedBlockingQueue 和 ArrayBlockingQueue 是 Java 中的两种阻塞队列实现,它们的主要区别在于: 1. **数据结构**:ArrayBlockingQueue 采用固定大小的数组实现,而 LinkedBlockingQueue 则使用链表实现。 2. **容量**:ArrayBlockingQueue 在创建时必须指定容量,而 LinkedBlockingQueue 可以在创建时不指定容量,默认容量为 Integer.MAX_VALUE。 总结起来,如果需要高效并发且内存不是主要考虑因素,LinkedBlockingQueue 通常是更好的选择;
32 1
|
1月前
|
缓存 NoSQL Java
java中复杂业务情况下的集合操作(增减集合同步数据)
java中复杂业务情况下的集合操作(增减集合同步数据)
27 0
|
1月前
|
安全 Java 程序员
Java中的并发编程:掌握同步机制与线程安全
【2月更文挑战第12天】 在现代软件开发领域,多线程和并发编程已成为提高应用性能和资源利用率的关键技术。Java语言提供了丰富的并发编程工具和框架,使得开发高效、可靠的并发应用成为可能。本文将深入探讨Java中的并发编程,着重介绍同步机制、线程安全概念及其在实际开发中的应用。通过对这些知识点的深入分析和案例演示,旨在帮助读者建立起对Java并发编程的全面理解,从而更好地设计和实现线程安全的高并发系统。

热门文章

最新文章