简介:本文系统梳理Java并发编程的核心知识体系,从并发库整体架构入手,深入剖析锁机制、原子类、并发集合、线程池与同步工具的原理与实现要点,并结合典型代码示例说明常见陷阱与最佳实践。读者可借此建立完整的并发知识框架,提升在高并发场景下的设计与问题排查能力。
Java并发编程是后端开发面试与工程实践中的核心领域,其知识体系庞杂、细节繁多。本文将围绕并发库的整体架构展开,逐层深入讲解锁机制、原子类、并发集合、线程池与同步工具的原理与使用要点,帮助读者建立系统化的认知框架。
Java并发工具集中于 java.util.concurrent 包及其子包中,整体可划分为五大模块:
Lock 接口为核心,包含可重入锁、读写锁、Condition 条件队列,底层统一依托 AbstractQueuedSynchronizer(AQS)构建。AtomicInteger、AtomicLong、AtomicReference、AtomicStampedReference 等,用于无锁化的计数与状态更新。ConcurrentHashMap、CopyOnWriteArrayList 以及 BlockingQueue 接口下的多种阻塞队列实现。Executor、ExecutorService 接口为抽象,ThreadPoolExecutor 与 ScheduledThreadPoolExecutor 为核心实现,辅以工厂类简化创建。CountDownLatch、CyclicBarrier、Semaphore、Exchanger 等协作工具,用于线程间的协调与同步。这一分层设计的核心思想是:将同步状态的管理与线程的阻塞唤醒机制解耦,AQS 承担统一的排队与状态管理职责,各组件只需定义自身的状态语义。
可重入锁是最常用的显式锁,其典型使用范式如下:
public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {// 临界区代码} finally {lock.unlock();}}}
其核心特性包括:
state 字段记录重入次数。state 递增,释放时递减,归零后方可被其他线程获取。lockInterruptibly() 允许在等待锁的过程中响应中断,避免无限期阻塞。tryLock() 提供非阻塞或限时获取能力,便于实现降级策略与死锁规避。使用要点在于:解锁必须放在 finally 块中,否则临界区抛出异常将导致锁永久泄漏。
读写锁将共享资源的访问分为读、写两类,适用于读多写少的缓存场景:
public class ReadWriteLockExample {private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();private final Map<String, Object> cache = new HashMap<>();public Object get(String key) {rwLock.readLock().lock();try {return cache.get(key);} finally {rwLock.readLock().unlock();}}public void put(String key, Object value) {rwLock.writeLock().lock();try {cache.put(key, value);} finally {rwLock.writeLock().unlock();}}}
其语义规则为:
需要注意的是,读写锁的收益依赖读写比例,若写操作频繁,其额外开销可能反而降低性能;同时它不支持锁升级(读锁直接转写锁),需先释放读锁再获取写锁。
原子类基于 CAS(比较并交换)指令实现,避免了加锁带来的上下文切换开销。典型用法如下:
public class AtomicExample {private AtomicInteger counter = new AtomicInteger(0);private AtomicReference<String> reference = new AtomicReference<>("init");public void increment() {counter.incrementAndGet();}public boolean casReference(String expect, String update) {return reference.compareAndSet(expect, update);}}
关键点包括:
AtomicStampedReference 通过附加版本戳解决该问题。并发集合方面,ConcurrentHashMap 采用桶级锁或 CAS 加细粒度同步,显著优于全局加锁的同步容器;CopyOnWriteArrayList 通过写时复制实现读无锁,适合读多写极少且数据量可控的场景;BlockingQueue 家族则为生产者—消费者模型提供天然支持,其中数组结构有界队列内存可控,链表结构队列吞吐较高,优先级队列支持按优先级出队。
线程池方面,核心在于理解 ThreadPoolExecutor 的七个构造参数:核心线程数、最大线程数、空闲存活时间、任务队列、线程工厂、拒绝策略。其调度逻辑为:核心线程未满则新建线程;否则入队;队列满则扩容至最大线程数;仍无法处理则触发拒绝策略。合理配置需结合任务类型(CPU 密集或 IO 密集)、队列容量与拒绝策略综合权衡,避免无界队列导致内存膨胀。
wait/notify 协调逻辑。volatile 与 final,避免过度同步。掌握上述体系后,无论是应对面试中的原理追问,还是解决生产环境中的并发缺陷,都能做到有据可依、有条不紊。