JAVA面试——JAVA多线程并发(四)

简介: JAVA面试——JAVA多线程并发

4.1.24.什么是AQS 抽象的队列同步器

AbstractQueuedSynchronizer类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问 共享资源的同步器框架,许多同步类实现都依赖于它,如常用的

ReentrantLock/Semaphore/CountDownLatch

image.png

它维护了一个volatile int state (代表共享资源)和一个FIFO线程等待队列(多线程争用资源被 阻塞时会进入此队列)。这里volatile是核心关键词,具体volatile的语义,在此不述。state的 访问方式有三种:

getState

setState()

compareAndSetState()

AQS定义两种资源共享方式

Exclusive 独占资源-ReentrantLock

Exclusive (独占,只有一个线程能执行,如ReentrantLock)

Share 共享资源Semaphore/CountDownLatch

Share (共享,多个线程可同时执行,如Semaphore/CountDownLatch)

AQS只是一个框架,具体资源的获取/释放方式交由自定义同步器去实现AQS这里只定义了一个 接口,具体资源的获取交由自定义同步器去实现了(通过state get/set/CAS)之所以没有定义成 abstract是因为独占模式下只用实现tryAcquire-tryRelease而共享模式下只用实现 tryAcquireShared-tryReleaseShared如果都定义成abstract那么每个模式也要去实现另一模 式下的接口。不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实 现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/ 唤醒出队等),AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:

1. isHeldExclusivelyO该线程是否正在独占资源。只有用到condition才需要去实现它。

2. tryAcquire(int):独占方式。尝试获取资源,成功则返回true失败则返回false

3. tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false

4. tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余 可用资源;正数表示成功,且有剩余资源。

5. tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回 true否则返回false

同步器的实现是ABS 核心 (state资源状态计数)

同步器的实现是ABS核心,以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程 lock时,会调用tryAcquire()独占该锁并将state+1此后,其他线程再tryAcquire()时就会失 败,直到A线程unlock()state=0 (即释放锁)为止,其它线程才有机会获取该锁。当然,释放 锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意, 获取多少次就要释放多么次,这样才能保证state是能回到零态的。

CountDownLatch以例,任务分为N个子线程去执行,state也初始化为N (注意N要与 线程个数一致)。这N个子线程是并行执行的,每个子线程执行完后countDown一次,state CAS1。等到所有子线程都执行完后(即state=0)unpark()主调用线程,然后主调用线程 就会从await()函数返回,继续后余动作。

ReentrantReadWriteLock实现独占和共享两种方式

一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire- tryReleasetryAcquireShared-tryReleaseShared 中的一种即可。AQS 也支持自定义同步器 同时实现独占和共享两种方式,如ReentrantReadWriteLock

目录
相关文章
|
22天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
56 2
|
10天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
34 14
|
25天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
21天前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
27天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
18天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
28天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
52 4
|
7月前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。
|
4月前
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
67 1
|
5月前
|
安全 Java 开发者
Java并发编程中的线程安全问题及解决方案探讨
在Java编程中,特别是在并发编程领域,线程安全问题是开发过程中常见且关键的挑战。本文将深入探讨Java中的线程安全性,分析常见的线程安全问题,并介绍相应的解决方案,帮助开发者更好地理解和应对并发环境下的挑战。【7月更文挑战第3天】
100 0