前置理论
可重入锁
- 核心定义与特性 - 允许同一线程多次获取同一把锁而不会死锁 
- 重入计数器:每次获取锁时计数器递增,释放时递减,归零时锁完全释放 
- 线程标识绑定:锁内部记录当前持有锁的线程,确保只有持有者能重入 
- 避免递归死锁:线程在递归或嵌套方法中调用同一锁保护的代码时无需重复等待 
 
- 与不可重入锁的对比 - 不可重入锁:同一线程重复获取锁时会阻塞,导致死锁(如自旋锁在递归中无限等待) 
- 可重入锁优势:通过计数器机制安全重复进入同步区域,提升代码灵活性 
 
- Java 中的实现与应用 - ReentrantLock- 显式锁,支持公平性选择(公平锁按请求顺序分配,非公平锁允许插队) 
- 支持条件变量( - Condition)实现精准线程唤醒(如生产者-消费者模型的队列分离)
 
- synchronized关键字- 隐式可重入锁,功能有限(不支持中断或超时) 
 
 
- 典型应用场景 - 递归算法:递归函数多次获取同一锁保护共享资源 
- 同步嵌套调用:类中多个方法互斥访问共享资源且存在调用链 
- 复杂线程协作:通过 - Condition实现多等待队列(如任务调度优先级控制)
 
- 注意事项 - 锁释放匹配:每次获取锁必须对应释放,否则计数器无法归零导致死锁 
- 性能权衡:公平锁减少线程饥饿但增加切换开销,非公平锁反之 
- 避免过度嵌套:深层嵌套增加调试复杂度(需追踪计数器状态) 
 
核心策略
多线程安全保障的核心策略
- 同步机制 - 互斥锁 - synchronized:自动管理锁,适用于简单临界区(如计数器操作)
- ReentrantLock:支持可中断锁、公平锁及条件变量,适合复杂同步需求(如超时控制)
 
- 读写锁 - ReentrantReadWriteLock:读共享、写独占,提升读多写少场景性能(如缓存系统)
 
 
- 无锁编程 - 原子类 - AtomicInteger/- AtomicReference:基于 CAS 实现无锁线程安全操作(如高并发计数)
 
- 可见性控制 - volatile:保证变量修改的可见性,适用于简单状态标志(需结合锁保证原子性)
 
 
- 线程隔离与不可变设计 - 线程局部存储 - ThreadLocal:为每个线程提供独立变量副本(如会话管理),需调用- remove()防泄漏
 
- 不可变对象 - 对象状态不可修改(如 - String、不可变集合),天然线程安全
 
 
- 线程安全数据结构 - 并发集合 - ConcurrentHashMap:分段锁优化高并发读写,性能优于- HashTable
- CopyOnWriteArrayList:写时复制机制,适合读多写少场景(如事件监听器列表)
 
- 阻塞队列 - BlockingQueue:自动阻塞管理(如- LinkedBlockingQueue),简化生产者-消费者模型
 
 
- 并发工具类 - 任务协调工具 - CountDownLatch:主线程等待多个子任务完成(如服务初始化)
- CyclicBarrier:多线程同步至共同阶段后继续执行(如分批次数据处理)
 
- 资源控制工具 - Semaphore:控制资源并发访问量(如数据库连接池限流)
 
 
- 执行框架类 - 线程池管理 - ThreadPoolExecutor:灵活配置线程池参数(核心线程数、队列策略等)
 
- 异步任务管理 - FutureTask:封装异步计算结果,支持阻塞获取结果(如并行计算任务)
 
 
- 锁与条件类 - 高级锁机制 - StampedLock:乐观读锁,减少读写锁竞争(读多写少场景优化)
 
- 条件变量 - Condition:与- ReentrantLock配合,实现细粒度等待/唤醒(如生产者-消费者模型)
 
 
- 设计原则与优化 - 锁粒度控制 - 仅同步必要代码块(如共享变量操作),减少锁竞争时间 
 
- 死锁预防 - 统一锁顺序、设置超时( - tryLock)、使用检测工具(如- jstack)
 
- 性能优化策略 - 读多写少场景优先用无锁或乐观锁,高并发场景结合线程池管理 
 
 
公平锁 & 非公平锁
- 公平锁 - 获取顺序:严格按线程请求顺序分配锁,遵循“先到先得”原则,释放锁时队列中等待最久的线程优先获取 
- 实现机制 - 维护 FIFO 等待队列,通过 - hasQueuedPredecessors()检查队列状态
- 示例:Java 的 - ReentrantLock(true)在获取锁前检查队列
 
- 特点 - 优点:避免线程饥饿 
- 缺点:性能较低,因维护队列和线程切换开销增加 
 
 
- 非公平锁 - 获取顺序:允许线程直接竞争锁,新请求线程可能插队抢占锁,无需检查队列 
- 实现机制 - 直接尝试 CAS 获取锁,失败后才加入队列 
- 示例:Java 的 - ReentrantLock()默认模式
 
- 特点 - 优点:吞吐量高,减少线程调度开销 
- 缺点:可能导致线程饥饿 
 
 
- 核心区别 - 锁分配顺序:公平锁严格按队列顺序,非公平锁允许插队 
- 性能:非公平锁性能更高(减少线程切换),公平锁适合对公平性敏感的场景 
- 实现复杂度:公平锁需维护队列状态,非公平锁实现更简单 
 
- Java 中的实现 - ReentrantLock:通过构造函数参数 - true启用公平锁,默认或- false为非公平锁
- synchronized:底层固定为非公平锁,不支持配置 
 
- 适用场景 - 公平锁:需严格顺序的场景(如银行转账、任务调度) 
- 非公平锁:高并发且锁竞争不激烈(如缓存读取、短任务处理) 
 
吞吐量
非公平锁吞吐量为什么比公平锁大?
- 减少上下文切换开销 - 非公平锁允许新线程直接抢占锁,避免公平锁强制唤醒队列头部线程的上下文切换(耗时 1-10 微秒) 
- 刚释放锁的线程可能立即重新获取,减少线程状态切换次数 
 
- 利用 CPU 缓存局部性 - 非公平锁允许刚释放锁的线程(缓存未失效)快速重入,避免公平锁切换线程导致的缓存重新加载(延迟 100-300 纳秒) 
 
- 避免队列维护成本 - 非公平锁仅在竞争失败时加入队列,公平锁每次获取需检查队列状态(增加 20-50 纳秒/次开销) 
- 实验数据:64 线程时非公平锁吞吐量下降幅度比公平锁低 60%-80% 
 
- 减少线程挂起概率 - 锁持有时间短时,非公平锁有 30%-50% 概率让新线程直接获取锁,避免挂起和内核调度介入(耗时 1-5 微秒) 
 
- 优化系统调用频率 - 非公平锁通过 CAS 自旋减少 - park()系统调用次数,相同并发量下系统调用比公平锁减少 40%-70%
- 高并发测试(64 线程)中吞吐量可达公平锁的 5-8 倍 
 
死锁问题
- 死锁产生的核心条件 - 互斥条件:资源被独占使用(如数据库写锁) 
- 请求与保持:持有资源的同时请求新资源(如线程A持有锁1后请求锁2) 
- 不可剥夺:资源只能由持有者主动释放 
- 循环等待:形成等待链(如线程A→B→C→A) 
 
- 典型死锁场景 - 多线程嵌套锁:线程以不同顺序获取多个锁(如线程1锁A后锁B,线程2锁B后锁A) 
- 数据库事务冲突:事务交叉更新记录(如事务T1更新X后请求Y,T2更新Y后请求X) 
- 资源分配不合理:短任务高频竞争不可剥夺资源(如内存不足时进程互相等待) 
 
- 死锁解决方法 - 预防策略 - 统一资源申请顺序:按固定编号顺序获取锁(如先锁表A再锁表B) 
- 一次性申请所有资源:启动前声明所需全部资源 
 
- 动态避免 - 银行家算法:动态检测资源分配安全性 
- 超时机制:设置锁获取超时(如 - tryLock(5, TimeUnit.SECONDS))
 
- 检测与恢复 - 资源分配图检测:周期性扫描环路并终止部分进程 
- 事务回滚:数据库自动回滚代价最小的事务 
 
- 工程实践优化 - 减少锁粒度:使用读写锁(如 - ReentrantReadWriteLock)
- 无锁编程:采用 CAS(如 - AtomicInteger)或线程本地存储
 
 
- 不同场景的解决方案选择 - 高并发服务:非公平锁+超时检测(如电商秒杀系统用 - ReentrantLock)
- 金融交易系统:统一资源访问顺序+事务隔离级别(按账户ID升序更新) 
- 实时操作系统:资源抢占机制(允许高优先级进程回收资源) 
 
synchronized锁
定义
- 核心作用 - 通过内置锁机制确保多线程环境下共享资源的原子性和可见性 
- 基于对象监视器(Monitor)控制线程对同步代码的访问,同一时刻仅允许一个线程执行锁定代码 
 
- 三种使用方式 - 修饰实例方法 - 锁对象:当前实例( - this)。
- 场景:保护实例变量的线程安全操作,如多线程操作同一对象的计数器 
 
- 修饰静态方法 - 锁对象:类的 - Class对象(- ClassName.class)
- 场景:保护静态变量的线程安全操作,如全局计数器或单例初始化 
 
- 修饰代码块 - 锁对象:可指定任意对象(如 - this、自定义锁)
- 场景:缩小锁粒度提升性能,仅对关键代码段加锁 
 
 
使用
- 典型应用场景 - 共享资源的原子操作 - 需保证复合操作完整性的场景,如计数器增减、转账操作、库存扣减 
 
- 单例模式的双重检查锁定 - 延迟初始化且保证线程安全,如全局配置类、数据库连接池 
 
- 线程安全的数据结构 - 保护集合类的并发修改,如 - Collections.synchronizedList包装的- ArrayList
 
- 生产者-消费者模型 - 协调线程间的数据传递,如消息队列的任务生产和消费 
 
 
- 注意事项 - 锁粒度控制 - 避免全方法加锁,优先同步关键代码段以减少竞争 
 
- 死锁预防 - 统一多锁的获取顺序(如按对象哈希值排序),避免循环等待 
 
- 性能优化 - 减少锁持有时间,利用 JVM 锁升级机制(偏向锁→轻量级锁→重量级锁) 
 
- 异常处理 - 在 - finally块中释放锁,防止线程阻塞导致资源泄漏
 
 
非公平锁
- synchronized 的公平性本质 - 底层实现默认且固定为非公平锁,不保证线程按请求顺序获取锁 
- 新请求线程可能直接抢占锁,而非遵循队列顺序 
 
- 非公平锁的核心表现 - 随机竞争机制:锁释放时 JVM 不检查队列顺序,新线程与队列线程随机竞争 
- 潜在饥饿风险:高频短任务场景中可能出现线程长期无法获取锁 
 
- 设计选择的原因 - 性能优先:减少线程唤醒和上下文切换(每次 1-10 微秒),吞吐量可达公平锁的 5-8 倍 
- 实现简化:锁升级机制(偏向锁→轻量级锁→重量级锁)针对非公平场景优化 
 
- 与 ReentrantLock 的对比 - 灵活性差异:ReentrantLock 可配置公平/非公平模式,synchronized 仅支持非公平 
- 适用场景 - synchronized:锁持有时间短、竞争不激烈(如计数器递增) 
- ReentrantLock 公平模式:需严格顺序的场景(如银行转账) 
 
 
静态 & 普通
synchronized 锁,静态方法和普通方法区别?
- 锁对象不同 - 普通方法:锁定当前实例对象( - this),同一实例的同步普通方法互斥,不同实例方法可并行执行
- 静态方法:锁定类的 - Class对象,所有实例调用同步静态方法均互斥,全局仅一个线程可执行
 
- 作用范围差异 - 普通方法:仅对同一对象实例的同步方法互斥,不同实例的同名方法不受影响 
- 静态方法:同一时间任何实例的同步静态方法均不可并行执行 
 
- 锁的粒度 - 普通方法:锁粒度较细,影响单个实例操作,适合高频实例级资源保护 
- 静态方法:锁粒度较粗,全局锁定类级别资源,可能成为性能瓶颈 
 
- 适用场景 - 普通方法:保护实例变量(如对象属性修改),避免多线程数据竞争 
- 静态方法:保护静态变量或实现类级同步逻辑(如单例模式双重检查锁定) 
 
- 线程交互影响 - 普通方法:不同线程访问不同实例的同步普通方法可并发执行 
- 静态方法:同一时间仅一个线程能执行静态同步方法(如全局配置更新) 
 
- 锁类型独立性 - 互不干扰:类锁与对象锁可同时持有(如线程持有类锁后仍可获取对象锁) 
- 锁升级机制:JVM 对两种锁均可能进行偏向锁、轻量级锁、重量级锁优化升级 
 
支持重入
- synchronized 支持重入 - 同一线程可多次获取同一对象的锁而不会阻塞,避免递归或嵌套调用导致的死锁 
 
- 实现原理 - 锁计数器与监视器机制 - 对象关联锁计数器( - status)和持有线程 ID,首次获取计数器置 1,重入时递增,释放时递减,归零后完全释放
 
- 字节码指令支持 - 通过 - monitorenter和- monitorexit指令控制代码块进入/退出时的锁状态检查与计数器更新
 
- 锁升级机制 - 无竞争时使用偏向锁记录线程 ID,竞争升级为轻量级锁(CAS 自旋),激烈竞争时转为重量级锁(操作系统互斥锁) 
 
 
- 优势与局限 - 优势 - 自动管理锁释放,避免死锁风险 
- 支持递归调用和嵌套同步代码块,简化编程逻辑 
 
- 局限 - 高并发场景下频繁锁升级(如偏向锁→重量级锁)可能带来性能损耗 
 
 
- 与显式锁的对比 - synchronized 的可重入性是隐式自动管理,而 - ReentrantLock需手动管理计数器
 
锁升级
注意高版本因为偏向锁性能收益低和实现过于复杂,已将偏向锁移除
- 无锁状态 - 对象创建时无锁,Mark Word 无锁标记,所有线程可自由访问 
 
- 偏向锁阶段 - 触发条件:第一个线程首次获取锁时,JVM 将对象头 Mark Word 设为偏向锁状态(锁标志位 01),记录线程 ID 
- 优化目的:单线程重复获取锁时无需同步操作,直接通过线程 ID 比对进入同步代码块 
- 撤销机制:其他线程尝试获取锁时,JVM 暂停持有线程,若锁已释放则升级为轻量级锁 
 
- 轻量级锁阶段 - 触发条件:多线程低竞争时升级(锁标志位 00) 
- 实现方式 - 线程栈帧创建锁记录(Lock Record),拷贝对象头 Mark Word 
- 通过 CAS 替换对象头为指向锁记录的指针,成功则获取锁,失败则自旋等待 
 
- 自旋优化:自适应策略动态调整自旋次数以减少 CPU 空转 
 
- 重量级锁阶段 - 触发条件:自旋次数超限或竞争激烈时升级(锁标志位 10) 
- 实现机制 - 依赖操作系统互斥量(Mutex)实现阻塞与唤醒,未获锁线程进入等待队列 
- 涉及用户态到内核态切换,带来高上下文切换开销 
 
- 不可逆性:升级后无法降级,即使竞争减弱仍保持该状态 
 
- 锁升级的意义 - 性能优化:减少低竞争场景同步开销(如偏向锁单线程优化) 
- 平衡机制:轻量级锁减少阻塞,重量级锁保障高并发有序执行 
- Mark Word 动态变化:对象头存储不同元数据(线程 ID、锁记录指针等) 
 
JVM优化
- 锁升级机制 - 轻量级锁 - 通过 CAS 操作和线程栈的锁记录实现非阻塞同步,首次获取时拷贝对象头 Mark Word 至锁记录,CAS 替换对象头指针 
- 自适应自旋策略动态调整自旋次数,减少 CPU 空转 
 
- 重量级锁 - 高竞争时升级为操作系统互斥锁(Mutex),依赖等待队列管理线程阻塞与唤醒 
- 用户态到内核态切换带来高开销,升级后不可逆 
 
 
- 锁消除 - JIT 编译器通过逃逸分析检测同步对象是否仅限当前线程使用,未逃逸时消除锁操作 
- 典型场景:未逃逸的局部变量(如方法内的 StringBuffer)同步被优化为无锁形式 
 
- 锁粗化 - 合并相邻同步代码块减少加锁/解锁开销,如循环体内多次同步合并为单次同步 
- 优化原则:临界区执行时间需远小于线程调度时间片(通常控制在 1 毫秒内) 
 
- 自适应锁优化 - 动态选择锁策略:低竞争时自旋等待,高竞争时直接阻塞线程 
- 自旋次数阈值基于历史竞争数据动态调整,平衡 CPU 利用率与响应速度 
 
- 偏向锁替代方案 - 现代 JVM(JDK 15+)移除偏向锁,优先采用锁消除和轻量级锁优化 
- 遗留支持:通过 - -XX:+UseBiasedLocking强制启用(官方不推荐)
 
- 其他优化策略 - Mark Word 复用:对象头动态存储线程 ID、锁记录指针等元数据 
- 可重入性:通过锁计数器实现同一线程多次获取锁,避免递归死锁 
- 锁粒度控制:低竞争用细粒度锁,高竞争改用显式锁(如 ReentrantLock) 
 
ReentrantLock
定义
- 定义 - ReentrantLock 的定义 
 
- 特性 - 可重入性:同一线程可多次获取同一锁,避免递归调用或嵌套同步块导致的死锁 
- 公平性选择:支持公平锁(按请求顺序分配)和非公平锁(默认模式),前者减少线程饥饿但吞吐量较低 
- 条件变量:通过 - newCondition()创建多个等待队列,实现细粒度线程协作(如生产者-消费者模型的不同唤醒条件)
- 锁超时与中断响应:提供 - tryLock(timeout, unit)和- lockInterruptibly(),支持超时获取锁和中断等待
- 锁状态监控:通过 - getHoldCount()查询锁重入次数,- isLocked()判断锁是否被占用
 
使用
- 应用场景 - 高竞争环境下的共享资源保护 - 多线程操作计数器、转账逻辑等需要原子性更新的场景,相比 - synchronized在高并发下性能更优
 
- 需要公平调度的系统 - 任务调度需按提交顺序处理请求的场景(如金融交易系统) 
 
- 复杂线程协作模型 - 生产者-消费者模型中结合 - Condition实现满队列和空队列的精准唤醒
- 阻塞队列通过 - tryLock控制入队/出队的超时逻辑
 
- 框架级并发控制 - 保护线程池状态(如 - ThreadPoolExecutor的- RUNNING状态)和任务队列的线程安全
- ConcurrentHashMap的分段锁机制中使用 ReentrantLock 控制哈希桶的并发访问
 
- 需要锁中断或超时响应的场景 - 分布式锁实现中通过 - tryLock避免线程因网络问题长期阻塞。
- 实时系统要求任务在指定时间内完成并执行降级策略 
 
 
- 注意事项 - 手动释放锁:必须在 - finally块中调用- unlock(),否则可能导致死锁或资源泄漏
- 避免锁嵌套:支持可重入但过度嵌套会增加锁竞争复杂度 
- 公平锁的权衡:仅在严格顺序需求时使用,避免增加线程切换开销 
- 性能监控:通过 - getQueueLength()监控等待线程数,优化锁竞争热点
 
公平锁
- 公平锁的核心实现机制 - FIFO 队列顺序: - 通过 - FairSync类实现,线程调用- lock()时必须先检查 AQS 队列是否存在等待线程- 队列为空或无前驱节点时尝试 CAS 获取锁 
- 队列存在等待线程时,当前线程加入队列尾部排队 
 
 
 
- 关键方法 - hasQueuedPredecessors()- 在 - tryAcquire()中调用该方法检查队列状态
- 确保只有队列头部线程能获取锁,阻止新线程插队 
 
- CLH 队列管理 - AQS 维护 CLH 双向链表队列,公平锁通过 - enq()将竞争失败的线程封装为 Node 节点加入队列尾部
- 锁释放时唤醒队列头部节点的线程,保证顺序执行 
 
- 与非公平锁的差异 - 初始抢占逻辑 - 公平锁:必须检查队列状态后才尝试 CAS 
- 非公平锁:直接 CAS 抢占,不检查队列 
 
- 性能表现 - 公平锁吞吐量较低(约下降 5-8 倍),适合顺序敏感场景 
- 非公平锁适合短任务竞争,吞吐量更高 
 
- 线程饥饿风险 - 公平锁无饥饿问题,非公平锁可能引发线程长期等待 
 
 
- 适用场景与代价 - 适用场景:支付系统、任务调度等需严格顺序的场景 
- 实现代价 - 每次锁获取需队列检查(增加 20-50 纳秒开销) 
- 频繁线程切换导致性能下降(对比非公平锁吞吐量降低 60%-80%) 
 
 
CountDownLatch
同步工具
- 核心功能 - 允许一个或多个线程等待其他线程完成特定操作后再继续执行 
- 内部维护计数器,初始化时指定等待的线程数量, - countDown()减少计数,计数器归零时唤醒等待线程
 
- 工作原理 - 初始化计数器: - new CountDownLatch(n)设置初始值- n(需等待的任务数)
- 任务完成通知:子线程调用 - countDown()安全减少计数(基于 CAS 实现)
- 阻塞与唤醒:主线程 - await()阻塞至计数器归零,支持超时- await(timeout, unit)
 
- 典型应用场景 - 主线程等待子任务完成:服务启动时等待所有组件初始化完毕 - CountDownLatch latch = new CountDownLatch(3); // 启动 3 个子线程初始化服务并调用 latch.countDown() latch.await(); // 阻塞至所有服务就绪
- 多线程结果汇总:并行计算后主线程汇总结果(如分片数据处理) 
- 并发测试同步:确保所有并发任务执行完毕后再验证结果 
- 资源协调:学生全部离场后通知家长,顾客到齐后服务员上菜 
 
- 注意事项 - 一次性使用:计数器归零后无法重置,需重新创建 
- 异常处理:子线程在 - finally中调用- countDown()避免主线程永久阻塞
- 超时机制:建议设置 - await()超时防止系统僵死
- 精确计数:初始值与实际任务数严格匹配(过多导致阻塞,过少提前唤醒) 
 
AQS
定义
- AQS 的基本概念与核心功能 - 定义:Java 并发包(JUC)的核心框架,用于构建锁和同步器(如 ReentrantLock、Semaphore、CountDownLatch) 
- 核心功能: - 通过 - volatile int state管理资源状态,支持原子操作(- getState()/- setState()/CAS)
- 基于 CLH 队列实现线程排队与唤醒,通过 LockSupport 实现线程阻塞( - park())与唤醒(- unpark())
 
 
- 底层实现原理 - 同步队列(CLH 队列) - 结构:双向链表,节点(Node)包含线程、等待状态( - waitStatus)及前后指针
- 作用:存储未获取资源的线程,实现 FIFO 公平调度,头节点( - head)表示当前持有资源的线程
 
- 条件队列 - 单向链表,用于 - Condition的等待/通知机制(如- await()和- signal())
 
 
- 资源共享模式 - 独占模式 - 同一时刻仅一个线程访问资源(如 ReentrantLock),通过 - tryAcquire()/- tryRelease()实现
- 可重入性: - state记录同一线程多次获取锁的计数
 
- 共享模式 - 允许多线程同时访问资源(如 Semaphore、CountDownLatch),通过 - tryAcquireShared()/- tryReleaseShared()实现
 
 
- 典型应用场景 - 锁实现:ReentrantLock 重写 - tryAcquire()实现公平/非公平锁
- 同步器: - CountDownLatch: - state初始化为计数值,- countDown()递减,归零时唤醒所有等待线程
- Semaphore:通过 - state控制并发线程数,- acquire()/- release()操作许可
 
 
- 优势与设计特点 - 模板方法模式:子类仅需实现 - tryAcquire()/- tryRelease()等模板方法,AQS 自动处理队列管理与调度
- 性能优化: - 双向链表支持快速删除节点(如线程超时或中断时) 
- 自旋优化减少上下文切换开销 
 
- 可扩展性:通过组合 AQS 实现复杂同步策略(如读写锁分离) 
 
可重入公平锁
- 核心实现原理 - 公平性保证 - 通过 AQS 的 CLH 队列实现线程 FIFO 排队,在 - tryAcquire()中调用- hasQueuedPredecessors()检查队列是否有等待线程
 
- 可重入性 - 通过 - state变量记录锁持有次数,同一线程多次获取时递增- state,释放时递减至归零
 
 
- 关键实现步骤 - 定义 Sync 类继承 AQS - 创建 - ReentrantFairLock类,内部定义- Sync类继承- AbstractQueuedSynchronizer
 
- 重写 tryAcquire 方法 - 检查 - state == 0:若无等待线程且 CAS 设置- state成功,获取锁并设置独占线程
- 若当前线程是持有者, - state += acquires实现可重入
 
- 重写 tryRelease 方法 - 递减 - state,归零时清空独占线程标识
 
 
- 公平锁与非公平锁区别 - 公平锁:强制检查队列状态,仅无等待线程时尝试获取锁 
- 非公平锁:允许直接 CAS 抢占锁,无需检查队列 
 
- 锁操作流程 - 加锁: - lock()调用失败时,线程进入 CLH 队列并阻塞,等待前驱节点唤醒
- 解锁: - unlock()释放锁后,唤醒队列中下一个线程
 
- 性能与注意事项 - 公平性代价:获取锁需遍历队列,吞吐量低于非公平锁 
- 重入限制: - lock()与- unlock()次数需严格匹配,否则导致死锁或状态异常
 
 
             
           
             
                         
             
            
评论区