线程池负责单机内任务调度,分布式锁保障跨机数据一致性;二者协同实现高并发下库存扣减等场景的正确性,需注意锁粒度、拒绝策略与锁续期等细节。

线程池负责单机内任务的高效调度与复用,分布式锁解决多机间资源互斥问题——二者配合,才能真正守住高并发下的数据一致性底线。
明确分工:线程池管“内部调度”,分布式锁管“跨机协调”
单台机器上,大量请求涌入时,线程池(如 ThreadPoolExecutor)控制并发线程数、排队策略和拒绝行为,避免系统过载;但它对其他机器完全无感知。一旦多个实例同时操作同一份共享变量(比如库存计数器、用户积分余额),就必须靠分布式锁来划出“谁当前有资格修改”的边界。
关键逻辑是:每个任务在执行前,先尝试获取分布式锁;只有成功拿到锁的线程,才进入线程池分配的执行单元中处理业务;处理完毕后立即释放锁。
典型协作流程(以秒杀扣减库存为例)
- 用户下单请求到达任意一台应用服务器
- 该服务调用 Redis 分布式锁(如基于 SETNX + 过期时间 + 唯一 client ID 的实现),锁 key 为
lock:product:1001 - 获取锁成功 → 提交任务到本地线程池(例如核心线程数设为 CPU 核心数 × 2,队列类型用
LinkedBlockingQueue防止无限堆积) - 线程池中线程执行实际逻辑:查库存、校验、扣减、更新 DB/缓存
- 无论成功或异常,都确保在 finally 块中主动释放分布式锁(不能依赖超时自动释放)
必须注意的三个实战细节
锁粒度要匹配业务范围:不要用全局锁(如 lock:all)保护所有商品,应按商品 ID 细分,否则变成串行处理,吞吐量归零。
线程池拒绝策略需配合降级:当分布式锁竞争激烈、大量请求排队等待时,线程池若已满,建议采用 CallerRunsPolicy 或自定义策略,让调用方线程自己执行(可触发限流告警),而不是简单丢弃任务。
锁续期与防误删:若业务耗时可能超过锁 TTL(如数据库慢查询),需引入看门狗机制自动续期;同时释放锁时必须比对 client ID,防止 A 机器误删 B 机器持有的锁。
推荐组合配置参考
以 4 核 8G 的 Java 应用节点为例:
- 线程池:corePoolSize = 8,maxPoolSize = 16,keepAliveTime = 60s,workQueue =
new LinkedBlockingQueue(200) - 分布式锁:Redis 单节点(或 Redlock 多节点)+ Lua 脚本原子释放 + 默认 TTL = 30s + client ID 随机 UUID
- 兜底保障:DB 悲观锁(
SELECT ... FOR UPDATE)作为分布式锁失效时的最后一道防线

















