Java并发编程进阶:从线程池到AQS深度剖析

Java并发编程进阶:从线程池到AQS深度剖析

在高并发系统开发中,Java并发编程是每个后端工程师必须掌握的核心技能之一。本文将从基础到进阶,带你全面了解线程池、锁机制、CAS与AQS原理,并通过实际代码案例帮助你理解如何在项目中应用这些技术。

目录

  1. 线程池原理与最佳实践
  2. Synchronized与volatile关键字详解
  3. CAS与Atomic原子类实现机制
  4. AQS(AbstractQueuedSynchronizer)原理深度解析
  5. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
  6. 实战:使用线程池+Redis+CAS构建高并发库存扣减服务

一、线程池原理与最佳实践

什么是线程池?

线程池是一种基于“池化”思想管理线程的技术,它可以复用线程资源,减少线程频繁创建销毁带来的性能损耗。

ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {
    System.out.println("执行任务");
});
executor.shutdown();
线程池参数详解
  • corePoolSize: 核心线程数
  • maximumPoolSize: 最大线程数
  • keepAliveTime: 空闲线程存活时间
  • unit: 时间单位
  • workQueue: 任务队列
  • threadFactory: 线程工厂
  • handler: 拒绝策略(AbortPolicy、CallerRunsPolicy等)

推荐使用ThreadPoolTaskExecutor代替Executors以避免OOM。


二、Synchronized与volatile关键字详解

synchronized作用
  • 保证同步代码块/方法最多只有一个线程执行
  • 可重入性
  • 阻塞式锁
public class SyncDemo {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }
}
volatile关键字的作用
  • 保证变量可见性
  • 禁止指令重排序
  • 不具备原子性(需配合CAS)
private volatile boolean running = true;
public void stop() {
    running = false;
}

三、CAS与Atomic原子类实现机制

什么是CAS?

CAS(Compare and Swap)是一种无锁算法,在硬件层面上提供了原子操作的支持。

AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.compareAndSet(0, 1);
CAS缺点
  • ABA问题
  • 循环时间长可能导致CPU开销过大
  • 只能保证单个变量的原子操作

四、AQS(AbstractQueuedSynchronizer)原理深度解析

AQS是JUC包下许多并发工具的基础框架,如ReentrantLock、Semaphore、CountDownLatch都基于AQS实现。

AQS核心机制
  • 使用int类型的state表示同步状态
  • FIFO队列管理等待线程
  • 支持独占模式(如ReentrantLock)与共享模式(如Semaphore)
public class MyLock extends AbstractQueuedSynchronizer {
    @Override
    protected boolean tryAcquire(int arg) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    @Override
    protected boolean tryRelease(int arg) {
        setState(0);
        setExclusiveOwnerThread(null);
        return true;
    }

    public void lock() { acquire(1); }
    public void unlock() { release(1); }
}

五、并发工具类详解

CountDownLatch

倒计时门闩,用于等待多个线程完成后再继续执行。

CountDownLatch latch = new CountDownLatch(3);
new Thread(() -> {
    System.out.println("任务1完成");
    latch.countDown();
}).start();
latch.await();
System.out.println("所有任务已完成");
CyclicBarrier

循环屏障,适用于多线程协同计算场景

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("所有线程已就位,开始执行...");
});

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        try {
            barrier.await();
            System.out.println(Thread.currentThread().getName() + " 执行完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}
Semaphore

信号量控制资源访问数量

Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
    new Thread(() -> {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + " 正在使用资源");
            Thread.sleep(1000);
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

六、实战:使用线程池+Redis+CAS构建高并发库存扣减服务

场景描述

电商平台秒杀系统中需要防止超卖现象,要求高并发情况下库存准确且不能为负。

@Service
public class StockService {
    @Autowired
    private RedisTemplate redisTemplate;
    private ExecutorService executor = Executors.newFixedThreadPool(10);

    public void deductStock(String productId) {
        String stockKey = "stock:" + productId;
        String script = "if redis.call('get', KEYS[1]) > 0 then return redis.call('decr', KEYS[1]) else return -1 end";
        DefaultRedisScript redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Long.class);
        Long result = redisTemplate.execute(redisScript, List.of(stockKey));
        if (result == null || result < 0) {
            throw new RuntimeException("库存不足");
        }
    }

    public void asyncDeductStock(String productId) {
        executor.submit(() -> {
            deductStock(productId);
        });
    }
}
设计亮点
  • Redis Lua脚本确保原子性
  • 线程池异步处理请求降低延迟
  • 采用CAS机制控制并发写入

总结

本文从并发基础讲到高级并发编程技巧,涵盖了线程池、锁优化、CAS、AQS、并发工具类等多个关键点,并通过真实电商秒杀库存扣减案例展示了如何在项目中落地这些技术。建议读者结合源码深入理解每种机制背后的设计哲学,这对提升架构能力有很大帮助。

你可能感兴趣的:(Java全栈面试指南,Java并发编程,线程池,AQS,CAS,volatile,Synchronized,Redis)