全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 9 分钟 ✍️ juanwangdev

Java并发编程与锁优化

并发编程在高性能场景下尤为重要,合理的锁策略能大幅提升吞吐量。

锁的类型与选择

锁类型特点适用场景
synchronizedJVM内置,简单低竞争场景
ReentrantLock灵活,可中断高竞争场景
StampedLock读写锁,乐观读读多写少
CAS无锁,乐观状态更新
LongAdder分散计数高并发计数

synchronized优化

锁升级过程

Java
┌─────────────────────────────────────┐
│         synchronized锁升级          │
├─────────────────────────────────────┤
│                                     │
│  无锁 → 偏向锁 → 轻量锁 → 重量锁     │
│                                     │
│  单线程   单线程   多线程交替  多线程竞争 │
│  无竞争   可重入   CAS自旋    阻塞等待 │
│                                     │
└─────────────────────────────────────┘

锁优化技巧

Java
// 1. 减小锁范围
public void process() {
    synchronized(this) {
        // 只锁必要代码
        criticalSection();
    }
    nonCriticalSection();  // 不锁
}

// 2. 锁分离(读写分离)
public class ReadWriteLockDemo {
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public Object read() {
        lock.readLock().lock();
        try {
            return data;
        } finally {
            lock.readLock().unlock();
        }
    }

    public void write(Object value) {
        lock.writeLock().lock();
        try {
            data = value;
        } finally {
            lock.writeLock().unlock();
        }
    }
}

// 3. 锁分段
public class StripedLock {
    private final Lock[] locks = new Lock[16];

    public void process(int key) {
        locks[key & 0xF].lock();  // 按key分段加锁
        try {
            // ...
        } finally {
            locks[key & 0xF].unlock();
        }
    }
}

无锁编程

CAS原子操作

Java
// AtomicInteger内部使用CAS
public class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public int increment() {
        return count.incrementAndGet();  // CAS自增
    }
}

// AtomicReference
public class AtomicUpdater {
    private AtomicReference<State> state = new AtomicReference<>();

    public boolean update(State oldState, State newState) {
        return state.compareAndSet(oldState, newState);
    }
}

LongAdder高并发计数

Java
// 高并发计数:LongAdder优于AtomicInteger
public class HighConcurrencyCounter {
    private LongAdder counter = new LongAdder();

    public void increment() {
        counter.increment();  // 分散计数,无竞争
    }

    public long sum() {
        return counter.sum();  // 汇总所有计数器
    }
}

// 对比:
// AtomicInteger:所有线程竞争一个变量
// LongAdder:分散到多个Cell,无竞争,最后汇总

并发容器选择

ConcurrentHashMap

Java
// JDK7:分段锁(Segment)
// JDK8:CAS+synchronized(桶级锁)

ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();

// 原子操作
map.putIfAbsent("key", "value");
map.computeIfAbsent("key", k -> computeValue());

// 批量操作(JDK8+)
map.forEach((k, v) -> process(k, v));
map.search(100, (k, v) -> searchValue(k, v));

CopyOnWriteArrayList

Java
// 适用:读多写极少
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

// 读:不加锁,直接返回
String value = list.get(0);

// 写:复制整个数组,加锁
list.add("new");  // 复制+加锁,性能低

并发队列

Java
// 高吞吐:ConcurrentLinkedQueue(无锁)
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("item");
String item = queue.poll();

// 阻塞队列:生产消费场景
ArrayBlockingQueue<String> bounded = new ArrayBlockingQueue<>(100);
bounded.put("item");  // 满时阻塞
String item = bounded.take();  // 空时阻塞

// 高性能阻塞队列:Disruptor
// RingBuffer实现,单线程可达百万级吞吐

线程池优化

线程池配置

Java
// 合理配置线程数
// CPU密集型:N + 1(N=CPU核数)
// IO密集型:2N 或更多

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    8,      // 核心线程数
    16,     // 最大线程数
    60,     // 空闲线程存活时间
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(1000),  // 任务队列
    new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
);

线程池监控

Java
// 监控线程池状态
executor.getActiveCount();      // 活动线程数
executor.getQueue().size();     // 队列大小
executor.getCompletedTaskCount(); // 完成任务数

// 动态调整
executor.setCorePoolSize(10);
executor.setMaximumPoolSize(20);

并发编程模式

生产者-消费者

Java
public class ProducerConsumer {
    private BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);

    // 生产者
    public void produce(String item) throws InterruptedException {
        queue.put(item);
    }

    // 消费者
    public String consume() throws InterruptedException {
        return queue.take();
    }
}

Future异步计算

text
// CompletableFuture(JDK8+)
CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> fetchData())
    .thenApply(data -> processData(data))
    .thenAccept(result -> saveResult(result));

// 组合多个Future
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> fetch1());
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> fetch2());
CompletableFuture<String> combined = f1.thenCombine(f2, (r1, r2) -> merge(r1, r2));

锁优化总结

场景推荐方案
低竞争synchronized
高竞争读多写少StampedLock乐观读
高竞争写多ReentrantLock
状态更新CAS/AtomicXxx
高并发计数LongAdder
高并发MapConcurrentHashMap
读多写极少CopyOnWriteArrayList
生产消费BlockingQueue

注意事项

synchronized已优化,低竞争场景足够

避免锁嵌套,防止死锁

LongAdder适合计数,AtomicInteger适合精确值

CopyOnWrite写操作性能差,只适合读多写极少

线程池队列大小影响响应时间和吞吐量

CompletableFuture适合异步编排,避免阻塞

要点总结

  1. synchronized锁升级:无锁→偏向→轻量→重量
  2. 高并发用CAS/LongAdder,无锁编程
  3. ConcurrentHashMap分段/桶级锁,高并发安全
  4. 线程池配置:CPU密集N+1,IO密集2N
  5. CompletableFuture异步编排,避免阻塞等待

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java常见性能问题排查
下一篇 → Java性能分析工具使用
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库