当前位置: 首页 > ops >正文

北京JAVA基础面试30天打卡03

1.AQS(AbstractQueuedSynchronizer)

AQS(AbstractQueuedSynchronizer) 是 Java 并发包(java.util.concurrent)中的一个核心框架类,用于构建锁和同步器(如 ReentrantLock、Semaphore、CountDownLatch 等)。它提供了一种基于队列的同步机制,管理线程的阻塞和唤醒。

核心思想

AQS 通过一个 FIFO 队列(基于 CLH 锁队列的变种)和一个 状态变量(int state)来实现线程同步:

  • 状态变量:表示锁或同步器的状态(如锁是否被占用,计数器的值等)。
  • 队列:维护等待获取锁的线程,线程进入队列后会被阻塞,直到满足条件被唤醒。
  • CAS 操作:通过 Compare-And-Swap(如 compareAndSetState)实现状态的原子更新。
工作原理
  1. 状态管理:AQS 维护一个 volatile int state,通过 CAS 操作修改状态。例如,ReentrantLock 中 state=0 表示锁空闲,state>0 表示锁被占用。

  2. 队列管理:当线程无法获取锁时,加入 AQS 的等待队列(CLH 队列),线程会被挂起(LockSupport.park)。

  3. 获取/释放

    • 获取锁:子类实现 tryAcquire 方法,尝试更新 state。成功则获取锁,失败则进入队列。
    • 释放锁:子类实现 tryRelease 方法,更新 state,并唤醒队列中的下一个线程(LockSupport.unpark)。
  4. 条件队列:AQS 支持 Condition 接口(如 ConditionObject),用于实现线程的条件等待(如 await 和 signal)。

核心方法
  • 模板方法

    (由 AQS 提供,子类实现):

    • tryAcquire(int):尝试获取锁。
    • tryRelease(int):尝试释放锁。
    • tryAcquireShared(int):尝试共享式获取资源。
    • tryReleaseShared(int):尝试共享式释放资源。
    • isHeldExclusively():判断锁是否独占。
  • 核心 API

    • acquire(int):获取锁(独占模式),包括尝试获取和入队阻塞。
    • release(int):释放锁,唤醒队列中的线程。
    • acquireShared(int) / releaseShared(int):共享模式的获取和释放。
使用场景

AQS 是许多 JUC 工具类的底层实现:

  • ReentrantLock:基于 AQS 实现可重入锁,state 表示锁的重入次数。
  • ReentrantReadWriteLock:读写锁,state 高 16 位表示读锁计数,低 16 位表示写锁状态。
  • Semaphore:信号量,state 表示可用许可数。
  • CountDownLatch:倒计数器,state 表示剩余计数。
  • CyclicBarrier:state 用于管理屏障状态。
优点
  • 灵活性:通过模板方法,子类可以自定义锁的语义。
  • 高效性:基于 CAS 和队列,减少上下文切换。
  • 可扩展性:支持独占锁、共享锁、条件等待等。

2. Synchronized 与 ReentrantLock 的区别

SynchronizedReentrantLock 都是 Java 中用于实现线程同步的机制,但它们在功能、性能和使用方式上有显著区别。

Synchronized
  • 定义:Java 关键字,内置的锁机制,由 JVM 管理。

  • 特点

    • 使用简单:通过 synchronized 关键字修饰代码块或方法,自动获取和释放锁。
    • 独占锁:同一时间只有一个线程可以持有锁。
    • 可重入:同一线程可以多次获取同一锁(锁计数器递增)。
    • 不可中断:线程在等待锁时无法被中断。
    • 自动释放:锁在代码块结束或异常时自动释放。
    • 无条件等待:不支持 Condition 机制,无法实现复杂等待/通知逻辑。
    • 性能:在 Java 6 之后,JVM 对 synchronized 进行了优化(如锁消除、锁粗化、偏向锁、轻量级锁),性能接近 ReentrantLock。
ReentrantLock
  • 定义:基于 AQS 实现的显式锁,位于 java.util.concurrent.locks 包。

  • 特点

    • 显式锁:需要手动调用 lock() 和 unlock() 获取/释放锁。
    • 可重入:与 synchronized 类似,支持重入。
    • 可中断:支持 lockInterruptibly(),允许线程在等待锁时被中断。
    • 公平/非公平:支持公平锁(按等待顺序分配)和非公平锁(默认,允许插队)。
    • 条件等待:支持 Condition 对象,可实现多个等待队列(如生产者-消费者模型)。
    • 灵活性:支持超时获取锁(tryLock(timeout))。
    • 手动释放:需在 finally 块中调用 unlock(),否则可能导致死锁。
区别总结
特性SynchronizedReentrantLock
实现方式JVM 内置,关键字JUC 包,基于 AQS
使用方式自动获取/释放锁手动 lock() / unlock()
可中断性不可中断可中断(lockInterruptibly)
公平性非公平锁可选公平锁或非公平锁
条件等待无 Condition 支持支持 Condition(多等待队列)
灵活性简单但功能有限功能丰富(超时、尝试锁等)
性能Java 6 后优化,接近 ReentrantLock稍高(尤其在复杂场景下)
异常处理自动释放锁需手动释放(finally 块)
使用场景
  • Synchronized:适合简单同步场景,如方法级或代码块级锁,代码简洁,适合快速开发。
  • ReentrantLock:适合需要高级功能的场景,如公平锁、可中断锁、条件等待、超时获取锁等。

代码示例

java

// Synchronizedsynchronized (obj) {// 同步代码块
}// ReentrantLock
ReentrantLock lock = new ReentrantLock();try {lock.lock();// 同步代码块
} finally {lock.unlock();
}

3. Java 中 volatile 关键字的作用

volatile 是 Java 中的一个关键字,用于修饰变量,确保变量在多线程环境下的可见性有序性,但不保证原子性

作用
  1. 保证可见性

    • 当一个线程修改了 volatile 变量的值,新值对其他线程立即可见。
    • 这是因为 volatile 变量的读写操作会直接与主内存交互,绕过线程的本地缓存(工作内存)。
    • 解决了多线程环境下缓存不一致的问题。
  2. 防止指令重排序

    • volatile 变量的读写操作会添加内存屏障(Memory Barrier),防止 JVM 或 CPU 进行指令重排序。
    • 确保代码的执行顺序与程序顺序一致(如初始化对象的正确性)。
  3. 不保证原子性

    • volatile 仅保证读写的原子性,但对复合操作(如 i++)不保证原子性。
    • 例如,volatile int i 的 i++ 操作分为读、改、写三步,多个线程可能交错执行,导致数据不一致。
使用场景
  • 状态标志:如 volatile boolean running = true,用于控制线程的启动/停止。
  • 单次写入,多次读取:如配置变量,初始化后只读不写。
  • 配合其他机制:与 synchronized 或 Atomic 类结合使用,解决原子性问题。
示例

java

class VolatileExample {volatile boolean flag = false;void writer() {flag = true; // 写入对其他线程立即可见}void reader() {if (flag) { // 读取到最新值System.out.println("Flag is true");}}
}
volatile 与 synchronized 的区别
  • volatile
    • 仅保证变量的可见性和有序性,不保证复合操作的原子性。
    • 轻量级,适用于简单场景(如标志位)。
  • synchronized
    • 保证原子性、可见性和有序性。
    • 重量级,适用于需要锁保护的复杂同步场景。
注意事项
  • volatile 不适合需要原子性的场景(如计数器),应使用 AtomicInteger 或 synchronized。
  • volatile 的性能开销低于 synchronized,但仍需谨慎使用,避免滥用。

总结

  • AQS:Java 并发框架的核心,基于状态变量和队列实现锁和同步器,广泛用于 JUC 工具类。
  • Synchronized vs ReentrantLock:Synchronized 简单但功能有限,ReentrantLock 提供更多灵活性(如公平锁、条件等待)。
  • volatile:确保变量的可见性和有序性,适合状态标志等场景,但不保证原子性。
  • 明天二次补充拓展,希望大家坚持下去,不见彩虹也有阳光~
http://www.xdnf.cn/news/17135.html

相关文章:

  • 数据大集网:企业贷获客数据平台,精准对接助贷获客平台与企业贷获客渠道
  • InfluxDB 集群部署与高可用方案(二)
  • 批量打印Excel条形码
  • 在Word和WPS文字中如何输入汉字的偏旁部首
  • 大数据之HBase
  • 沉寂半年,Kimi归来!
  • java 桌面应用程序基本框架
  • 应急响应linux
  • DDoS 防护的未来趋势:AI 如何重塑安全行业?
  • 深入理解SpringMVC DispatcherServlet源码及全流程原理
  • Flink CDC如何保障数据的一致性?
  • 亚矩阵云手机:解锁 Shopee/Lazada 东南亚电商运营“通关密码
  • WordPress自定义.js文件排序实现方法
  • Unity里的对象旋转数值跳转问题的原理与解决方案
  • Spring Boot集成方案 + Elasticsearch向量检索,语义搜索核弹
  • Linux seLinux
  • AI大语言模型如何重塑软件开发与测试流程
  • 3D开发引擎HOOPS赋能AEC领域:可视化技术助力建筑数字化转型!
  • Promise
  • 【JS-7-ajax】AJAX技术:现代Web开发的异步通信核心
  • Python包管理新利器:uv全面解析与Conda对比指南
  • 一文读懂:什么是CLIP
  • Redis集群核心原理与实战解析
  • C语言的数组与字符串练习题2
  • 【前端开发】四. JS内置函数
  • 5G毫米波射频前端测试:OTA暗室与波束成形性能验证
  • RuoYi-Cloud 微服务本地部署详细流程实录(IDEA + 本地 Windows 环境)
  • 商派小程序商城(小程序/官网/APP···)的范式跃迁与增长再想象
  • 参考线程池构建一个高性能、配置驱动的Docker容器池
  • 基于Simulink/MWORKS的文字与开关量混合传输系统设计