一、Lock体系

1. ReentrantLock(可重入锁)

Lock lock = new ReentrantLock();
lock.lock();
try {// 临界区代码
} finally {lock.unlock();
}
  • 特点:可重入、支持公平/非公平策略
  • 优势:可中断锁获取、定时锁等待
  • 使用场景:替代synchronized需要更灵活控制的场景
1. 核心使用场景
(1) 需要可中断的锁获取
ReentrantLock lock = new ReentrantLock();try {// 支持响应中断的锁获取lock.lockInterruptibly();try {// 执行可能长时间运行的任务processCriticalSection();} finally {lock.unlock();}
} catch (InterruptedException e) {// 处理中断逻辑handleInterruption();
}

典型场景

  • 实现可取消任务
  • 处理死锁恢复机制
  • 响应式系统中断处理
(2) 精确超时控制
if (lock.tryLock(300, TimeUnit.MILLISECONDS)) {try {// 临界区操作} finally {lock.unlock();}
} else {// 执行替代逻辑fallbackOperation();
}

适用场景

  • 高并发系统的熔断机制
  • 实时系统的时间敏感操作
  • 分布式锁的本地模拟
(3) 公平锁需求
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁public void fairAccess() {fairLock.lock();try {// 保证先到先得的访问顺序} finally {fairLock.unlock();}
}

适用场景

  • 交易撮合系统
  • 订单处理队列
  • 需要严格顺序执行的批处理
(4) 多条件变量
class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length)notFull.await();// ... put logicnotEmpty.signal();} finally {lock.unlock();}}
}

典型应用

  • 生产者-消费者模式
  • 阻塞队列实现
  • 复杂状态管理
6. 常见误区

误区 1:认为 ReentrantLock 总是比 synchronized 快

  • 在低竞争场景使用 synchronized

误区 2:忘记在 finally 中释放锁

总结建议
  1. 虚拟线程优先策略

    • 新项目直接使用 ReentrantLock
    • 旧系统逐步替换关键路径的 synchronized
  2. 锁选择决策树

    if (需要可中断/超时 || 需要公平性 || 虚拟线程环境)→ 选择 ReentrantLock
    else if (简单同步 && 短期持有)→ 使用 synchronized
    else→ 评估其他并发工具(如 StampedLock)
    
  3. 监控指标

    • 锁等待时间(超过 10ms 需要告警)
    • 虚拟线程固定率(目标 < 5%)
    • 锁竞争频率(每秒竞争次数)

通过深入理解 ReentrantLock 的机制和虚拟线程的协同工作原理,开发者可以构建出更高性能、更易维护的并发系统。在实际项目中,建议结合 APM 工具(如 Micrometer)持续监控锁使用情况,实现动态调优。

2. ReentrantReadWriteLock(读写锁)

ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();
  • 读写分离:共享读锁(允许多线程并发读),独占写锁
  • 锁降级机制:写锁可降级为读锁
  • 适用场景:读多写少的数据结构(如缓存)

3. StampedLock(邮戳锁)

StampedLock stampedLock = new StampedLock();
long stamp = stampedLock.tryOptimisticRead();
// 读取共享变量
if (!stampedLock.validate(stamp)) {// 升级为悲观读stamp = stampedLock.readLock();// ...stampedLock.unlockRead(stamp);
}
  • 三种模式:写锁、悲观读、乐观读
  • 无重入特性,需防止死锁
  • 性能优势:乐观读不阻塞写操作

4. LockSupport(线程阻塞工具)

Thread thread = new Thread(() -> {LockSupport.park();// 被唤醒后执行
});
thread.start();
LockSupport.unpark(thread);
  • 基于许可证的线程控制
  • 精准唤醒指定线程
  • 底层Unsafe类实现

5. SpinLock(自旋锁实现示例)

public class SpinLock {private AtomicBoolean locked = new AtomicBoolean(false);public void lock() {while (!locked.compareAndSet(false, true)) {// 自旋等待}}public void unlock() {locked.set(false);}
}
  • 适用场景:临界区代码执行时间极短
  • 优点:避免线程上下文切换
  • 缺点:CPU空转消耗资源

6. Condition(条件变量)

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();// 等待方
lock.lock();
try {condition.await();
} finally {lock.unlock();
}// 通知方
lock.lock();
try {condition.signal();
} finally {lock.unlock();
}
  • 实现精准的线程等待/通知机制
  • 支持多个等待队列
  • 典型应用:阻塞队列实现

二、并发工具类

1. AbstractQueuedSynchronizer(AQS)

// 自定义同步器示例
class Mutex extends AbstractQueuedSynchronizer {protected boolean tryAcquire(int acquires) {return compareAndSetState(0, 1);}protected boolean tryRelease(int releases) {setState(0);return true;}
}
  • CLH队列管理等待线程
  • 模板方法设计模式
  • 同步状态原子管理

2. CountDownLatch(倒计时门闩)

CountDownLatch latch = new CountDownLatch(3);// 工作线程
new Thread(() -> {// 完成任务latch.countDown();
}).start();// 主线程等待
latch.await();
  • 一次性使用
  • 典型应用:并行任务初始化

3. CyclicBarrier(循环屏障)

CyclicBarrier barrier = new CyclicBarrier(3, () -> {// 所有线程到达后执行
});new Thread(() -> {// 执行任务barrier.await();
}).start();
  • 可重复使用
  • 支持屏障动作
  • 应用场景:多阶段并行计算

4. Exchanger(数据交换器)

Exchanger<String> exchanger = new Exchanger<>();new Thread(() -> {String data = exchanger.exchange("Thread1 Data");
}).start();new Thread(() -> {String data = exchanger.exchange("Thread2 Data");
}).start();
  • 双线程数据交换
  • 支持超时机制
  • 应用场景:管道式处理

5. Phaser(阶段同步器)

Phaser phaser = new Phaser(3);new Thread(() -> {phaser.arriveAndAwaitAdvance();// 阶段1任务phaser.arriveAndDeregister();
}).start();
  • 动态注册机制
  • 分阶段任务控制
  • 支持分层结构

6. Semaphore(信号量)

// 创建包含3个许可的信号量(公平模式)
Semaphore semaphore = new Semaphore(3, true);// 获取许可(阻塞方式)
semaphore.acquire();
try {// 访问共享资源(最多3个线程并发)
} finally {semaphore.release();
}// 非阻塞尝试获取
if (semaphore.tryAcquire(1, TimeUnit.SECONDS)) {try {// 临界区操作} finally {semaphore.release();}
}
核心特性:
  1. 资源池管理

    • 通过许可(permits)控制并发访问数量
    • 许可数量可以动态调整(reducePermits/increasePermits
  2. 灵活获取方式

    • 支持批量获取(acquire(int permits)
    • 提供可中断/不可中断获取方式
    • 支持超时机制(tryAcquire
  3. 公平性选择

    • 非公平模式(默认):吞吐量优先
    • 公平模式:按请求顺序分配许可
典型应用场景:
  1. 连接池限流
// 数据库连接池实现
public class ConnectionPool {private final Semaphore semaphore;private final BlockingQueue<Connection> pool;public ConnectionPool(int size) {this.semaphore = new Semaphore(size);this.pool = new ArrayBlockingQueue<>(size);// 初始化连接...}public Connection getConnection() throws InterruptedException {semaphore.acquire();return pool.take();}public void release(Connection conn) {pool.offer(conn);semaphore.release();}
}
  1. 限流控制系统
// API限流控制器(每秒10个请求)
class RateLimiter {private final Semaphore semaphore = new Semaphore(10);private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public RateLimiter() {scheduler.scheduleAtFixedRate(() -> {int available = semaphore.availablePermits();if (available < 10) {semaphore.release(10 - available);}}, 0, 1, TimeUnit.SECONDS);}public boolean tryAcquire() {return semaphore.tryAcquire();}
}
  1. 生产者-消费者模型
// 有界缓冲区实现
class BoundedBuffer<E> {private final Semaphore availableItems;private final Semaphore availableSpaces;private final Queue<E> queue = new LinkedList<>();public BoundedBuffer(int capacity) {availableItems = new Semaphore(0);availableSpaces = new Semaphore(capacity);}public void put(E item) throws InterruptedException {availableSpaces.acquire();synchronized (this) {queue.offer(item);}availableItems.release();}public E take() throws InterruptedException {availableItems.acquire();E item;synchronized (this) {item = queue.poll();}availableSpaces.release();return item;}
}
使用技巧:
  1. 许可动态调整
// 运行时动态扩展容量
void resize(int newCapacity) {int delta = newCapacity - semaphore.availablePermits();if (delta > 0) {semaphore.release(delta);  // 扩容} else {semaphore.reducePermits(-delta);  // 缩容}
}
  1. 死锁预防
// 使用tryAcquire避免死锁
if (semaphore.tryAcquire(2, 100, TimeUnit.MILLISECONDS)) {try {// 临界区操作} finally {semaphore.release(2);}
} else {// 处理获取失败逻辑
}
  1. 与ReentrantLock对比
特性SemaphoreReentrantLock
资源控制多许可控制单锁独占
可重入性不支持支持
公平性可配置可配置
条件变量支持Condition
使用场景资源池/流量控制互斥操作
注意事项:
  1. 释放次数匹配

    • 确保acquire()与release()调用次数匹配
    • 使用try-finally保证释放
  2. 不可重入特性

    • 同一线程多次acquire需要对应次数的release
  3. 性能监控

    • 通过availablePermits()监控系统负载
    • 使用getQueueLength()检测等待线程数
  4. 资源泄漏预防

    • 建议使用带超时的tryAcquire
    • 结合Thread.interrupt()处理阻塞线程
源码关键实现:
// 基于AQS的Sync内部类
abstract static class Sync extends AbstractQueuedSynchronizer {Sync(int permits) {setState(permits);}final int getPermits() {return getState();}final int nonfairTryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}protected final boolean tryReleaseShared(int releases) {for (;;) {int current = getState();int next = current + releases;if (next < current) // overflowthrow new Error("Maximum permit count exceeded");if (compareAndSetState(current, next))return true;}}
}

五、最佳实践(补充)

  1. Semaphore使用准则:
    • 许可数量设置应基于系统压测结果
    • 避免在持有信号量时执行阻塞操作
    • 对不可靠资源访问添加finally释放块
    • 结合监控系统实现动态配额调整

通过Semaphore的合理使用,可以有效解决资源池管理、流量控制、系统过载保护等典型并发问题。其灵活的许可管理机制使其成为构建高弹性系统的利器,但需注意避免因错误使用导致的线程饥饿或系统死锁问题。

三、高性能计数器

1. LongAdder

LongAdder counter = new LongAdder();
counter.increment();
long sum = counter.sum();
  • 实现原理:
    • 基础值 + Cell数组分散竞争
    • 最终一致性保证
  • 适用场景:高频写、低频读

2. DoubleAdder

DoubleAdder adder = new DoubleAdder();
adder.add(1.5);
double sum = adder.sum();
  • 类似LongAdder的浮点版本
  • 注意精度问题
  • 适用场景:统计指标收集

3. 性能对比

计数器类型写性能读性能内存消耗适用场景
AtomicLong读写平衡场景
LongAdder写多读少场景

四、选型策略

  1. 锁机制选择:
  • 优先考虑synchronized
  • 需要高级功能时选择ReentrantLock
  • 读多写少场景使用StampedLock
  1. 并发工具选择:
  • 一次性等待用CountDownLatch
  • 多阶段任务用Phaser
  • 线程数固定用CyclicBarrier
  1. 计数器选择:
  • 普通场景使用AtomicLong
  • 高并发写场景使用LongAdder
  • 需要精确值时慎用DoubleAdder

五、最佳实践

  1. 避免锁嵌套使用
  2. 总是使用try-finally释放锁
  3. 合理设置超时时间
  4. 优先使用并发集合类
  5. 使用ThreadLocal减少竞争
  6. 监控锁竞争情况(JStack、JConsole)

本文深入剖析了Java并发编程的核心组件,开发者应根据具体场景选择最合适的工具。在高并发系统中,合理的锁选择和并发工具使用可以带来数量级的性能提升。建议结合JVM参数调优(如偏向锁、自旋参数)和并发监控工具进行综合优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/81203.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/81203.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/81203.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二个五年计划!

下一阶段&#xff01;5年后&#xff01;33岁&#xff01;体重维持在125斤内&#xff01;腰围74&#xff01; 健康目标&#xff1a; 体检指标正常&#xff0c;结节保持较小甚至变小&#xff01; 工作目标&#xff1a; 每年至少在一次考评里拿A&#xff08;最高S&#xff0c;A我理…

Redis(三) - 使用Java操作Redis详解

文章目录 前言一、创建项目二、导入依赖三、键操作四、字符串操作五、列表操作六、集合操作七、哈希表操作八、有序集合操作九、完整代码1. 完整代码2. 项目下载 前言 本文主要介绍如何使用 Java 操作 Redis 数据库&#xff0c;涵盖项目创建、依赖导入及 Redis 各数据类型&…

【Folium】使用离线地图

文章目录 相关文献离线地图下载Folium 使用离线地图 相关文献 Folium — Folium 0.19.5 documentationOffline Map Maker 离线地图下载 我们使用 Offline Map Maker 进行地图下载。 特别注意&#xff1a;Folium 默认支持 WGS84 坐标系&#xff0c;建议下载 WGS84 坐标系的地…

DeepSearch:字节新一代 DeerFlow 框架

项目地址&#xff1a;https://github.com/bytedance/deer-flow/ 【全新的 Multi-Agent 架构设计】独家设计的 Research Team 机制&#xff0c;支持多轮对话、多轮决策和多轮任务执行。与 LangChain 原版 Supervisor 相比&#xff0c;显著减少 Tokens 消耗和 API 调用次数&#…

Qt—用SQLite实现简单的注册登录界面

1.实现目标 本次实现通过SQLite制作一个简易的登录窗口&#xff0c;当点击注册按钮时&#xff0c;登录窗口会消失&#xff0c;会出现一个新的注册界面&#xff1b;完成注册或退出注册时&#xff0c;注册窗口会消失&#xff0c;重新出现登录窗口。注册过的用户信息会出现在SQLi…

day 18:零基础学嵌入式之数据结构——

一、基础内容 1.数据结构&#xff1a;相互之间存在一种或多种特定关系的数据元素的集合。 2.逻辑结构 &#xff08;1&#xff09;集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等。 &#xff08;2&#xff09;线性&#xff0c;数据和数据之间是一对一的关系 &am…

【SSL证书系列】客户端如何验证https网站服务器发的证书是否由受信任的根证书签发机构签发

客户端验证HTTPS网站证书是否由受信任的根证书颁发机构&#xff08;CA&#xff09;签发&#xff0c;是一个多步骤的过程&#xff0c;涉及证书链验证、信任锚&#xff08;Trust Anchor&#xff09;检查、域名匹配和吊销状态验证等。以下是详细的验证流程&#xff1a; 1. 证书链的…

iOS即时通信的技术要点

iOS即时通信开发的关键技术要点总结&#xff1a; 一、通讯协议选择 Socket通信 基础实现&#xff1a;使用原生BSD Socket或CFNetwork框架&#xff08;复杂&#xff09;&#xff0c;推荐第三方库如CocoaAsyncSocket&#xff08;封装GCDAsyncSocket&#xff09;&#xff0c;简化T…

智能AI构建工地安全网:跌倒、抽搐、区域入侵多场景覆盖

智能AI在工地安全中的应用&#xff1a;从监测到救援的全流程实践 一、背景&#xff1a;高温作业下的工地安全挑战 随着夏季高温持续&#xff0c;工地户外作业环境面临严峻考验。工人因高温疲劳、脱水或突发疾病引发的行为异常&#xff08;如晕厥、抽搐、跌倒&#xff09;频发…

Doris

Apache Doris&#xff08;原名&#xff1a;Palo&#xff09;是一个高性能、实时的MPP分析型数据库&#xff0c;非常适合海量数据的即席查询、报表分析、指标统计等 OLAP 场景。Doris 的设计目标是&#xff1a;极致查询性能、简单易用、支持高并发分析和明细查询。 一、Doris 核…

# 2-STM32F103-复位和时钟控制RCC

STM32-复位和时钟控制RCC 2-STM32-复位和时钟控制RCC摘要说明本文参考资料如下&#xff1a; 一、STM32最小系统回顾STM32F103C8T6核心板原理图 二、复位三、时钟3.1 时钟树3.2 STM32启动过程3.2 SystemInit()函数3.2.1 SystemInit()第1句&#xff1a;3.2.2 SystemInit()第2句&a…

rk3576 gstreamer opencv

安装gstreamer rk3588使用gstreamer推流_rk3588 gstreamer-CSDN博客 rk3588使用gstreamer推流_rk3588 gstreamer-CSDN博客 Installing on Linux sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-pl…

Quic如何实现udp可靠传输

QUIC&#xff08;Quick UDP Internet Connections&#xff09;是由 Google 设计并被 IETF 标准化的传输层协议&#xff0c;它基于 UDP 实现&#xff0c;但提供了类似 TCP 的可靠性和更高级的功能&#xff08;如多路复用、0-RTT 握手、TLS 加密等&#xff09;。 尽管 UDP 是不可…

uniapp-商城-59-后台 新增商品(属性的选中,进行过滤展示,filter,some,every和map)

前面讲了属性的添加&#xff0c;添加完成后&#xff0c;数据库中已经存在数据了&#xff0c;这时再继续商品的添加时&#xff0c;就可以进行属性的选择了。 在商品添加过程中&#xff0c;属性选择是一个关键步骤。首先&#xff0c;界面需要展示嵌套的属性数据&#xff0c;用户通…

负载均衡 ELB 在 zkmall开源商城高流量场景下的算法优化

在电商大促、直播带货等高频交易场景下&#xff0c;流量突发增长对系统稳定性提出严峻挑战。ZKmll 开源商城通过对负载均衡 ELB&#xff08;Elastic Load Balancer&#xff09;算法的深度优化&#xff0c;结合业务场景特性设计动态加权轮询 地域感知 热点分流的混合策略&…

Linux干货(三)

前言 从B站黑马程序员Linux课程摘选的学习干货&#xff0c;新手友好&#xff01;若有侵权&#xff0c;会第一时间处理。 目录 前言 1.which find命令 1.which命令 2.find命令 2.grep wc 管道符 1.grep命令 2.wc命令 3.管道符 3.echo tail 重定向符 1.echo命令 2.反…

Sigmoid与Softmax:从二分类到多分类的深度解析

Sigmoid与Softmax:从二分类到多分类的深度解析 联系 函数性质:二者都是非线性函数 ,也都是指数归一化函数,可将输入值映射为0到1之间的实数 ,都能把输出转化成概率分布的形式,在神经网络中常作为激活函数使用。Softmax是Sigmoid的推广:从功能角度看,Softmax函数可视为…

文件系统交互实现

关于之前的搭建看QT控件文件系统的实现-CSDN博客&#xff0c;接下来是对本程序的功能完善&#xff0c;我想着是这样设计的&#xff0c;打开一个目录以后&#xff0c;鼠标选中一个项可以是目录&#xff0c;也可以是文件&#xff0c;右键可以出现一个菜单选择操作&#xff0c;比如…

[ctfshow web入门] web75

信息收集 启用了open_basedir&#xff0c;所以之前的方法又不能用了 解题 cforeach(new DirectoryIterator("glob:///*") as $a){echo($a->__toString(). ); } ob_flush();cif ( $a opendir("glob:///*") ) {while ( ($file readdir($a)) ! false …

Vulfocus靶场-文件上传-3

WSO2 文件上传 &#xff08;CVE-2022-29464&#xff09; WSO2是一家成立于 2005 年的开源技术提供商。它提供了一个企业平台&#xff0c;用于在本地和整个 Internet 上 集成应用程序编程接口(API)、应用程序和 Web 服务。 某些 WSO2 产品允许无限制的文件上传和远程代码执行。…