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

Java并发编程核心组件简单了解

一、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.xdnf.cn/news/6572.html

相关文章:

  • 日志与策略模式
  • 正向代理和反向代理的区别?
  • LabVIEW图像粒子处理
  • 【LeetCode 热题 100】5. 最长回文子串(Python中心扩展法详解)
  • IOP出版|第二届人工智能、光电子学与光学技术国际研讨会(AIOT2025)
  • CCIE与HCIE哪个考试难度更大?
  • 如何将数据从一部手机传输到另一部手机 | 5 种便捷传输方式
  • 无人机减震模块运行与技术要点分析!
  • 关于 TCP 端口 445 的用途以及如何在 Windows 10 或 11 上禁用它
  • 深入 Linux 内核:GPU Runtime Suspend 源码和工作流程全面分析
  • 若依框架Consul微服务版本
  • [原创](计算机数学): 生日概率问题.
  • 电子电器架构 --- Zonal架构正在开创汽车电子设计新时代
  • 小刚说C语言刷题—1700请输出所有的2位数中,含有数字2的整数
  • 天能股份SAP系统整合实战:如何用8个月实现零业务中断的集团化管理升级
  • 升级kafka4.0.0,无ZK版本
  • android 安装openwrt 安正步骤
  • Android trace中CPU的RenderThread与GPU
  • 4.6. 暂退法(Dropout)笔记
  • 【沉浸式求职学习day41】【Servlet】
  • AWS SageMaker vs Bedrock:该选哪个?
  • 在 Visual Studio Code (VSCode) 中配置 MCP(Model Context Protocol)
  • 光学变焦和数字变倍模块不同点概述!
  • 1T 服务器租用价格解析
  • Centos7系统(最小化安装)安装zabbix7版本详细文章、nginx源代码配置、php源代码、mysql-yum安装
  • 基于对抗性后训练的快速文本到音频生成:stable-audio-open-small 模型论文速读
  • Fabric 服务端插件开发简述与聊天事件监听转发
  • 中科曙光服务器监控指标说明
  • 常见面试题
  • 电动流量调节V型球阀生产厂家|高精度耐磨控制阀解决方案-耀圣