并发用例设计是什么
并发缺陷难以稳定复现:设计用例时先明确并发实体(用户、线程、请求)、共享资源与交错点,再用屏障或同起点施压提高触发概率。典型目标包括超卖、重复编号、丢失更新与死锁,这些缺陷单独顺序执行时往往完全测不出来,只能靠构造并发交错暴露。
基本信息
| 三要素 | 并发实体、共享资源、交错点 |
|---|---|
| 工具支撑 | JMeter/k6 多虚拟用户、pytest-xdist 并行、线程屏障协调 |
| 数据要求 | 固定初始数据,失败后重建 |
| 断言重点 | 总量守恒、唯一性、最终一致性 |
典型使用场景
- 库存扣减:多用户同时下单验证不超卖
- 账户余额:并发转账验证总额守恒与无丢失更新
- 编号生成:并发送号验证全局唯一无重复
- 优惠券领取:同一券码被并发领取时只允许一次成功
- 订单提交:重复提交与超时重试叠加的处理
- 秒杀与抢购:同起点高并发下的限流与排队行为
- 连接池耗尽:并发下数据库连接被占满后的排队与恢复
Python 并发示例
Python 并发示例
import threading
barrier = threading.Barrier(20) # 20 个线程同一瞬间起跑
results = []
def worker():
barrier.wait() # 等齐后再一起施压
results.append(service.reserve('SKU-1', 1))
threads = [threading.Thread(target=worker) for _ in range(20)]
[t.start() for t in threads]
[t.join() for t in threads]
assert sum(1 for r in results if r.ok) == initial_stock # 成功数必须等于库存常见并发缺陷与断言
| 缺陷类型 | 触发条件 | 断言点 |
|---|---|---|
| 超卖 | 超过库存的并发扣减 | 成功笔数等于库存数 |
| 重复编号 | 并发申请同一序列 | 生成编号全局唯一 |
| 丢失更新 | 两个请求读改写覆盖 | 最终值等于预期叠加结果 |
| 死锁 | 交叉顺序加锁 | 超时内完成或优雅回滚 |
并发用例要固定初始数据并在失败后重建,否则多次运行结果互相污染;并行执行时每个用例使用独立账号与数据。
复现不稳定时先固定并发度与起点再调整参数:不确定的失败大多来自数据不干净或并发度不足,而不是产品没有缺陷。