ConcurrentQueue在典型多线程生产者-消费者场景下通常更快,尤其连接数≥数千时;因其采用CAS自旋而非锁阻塞,避免上下文切换,实测比Queue+lock快4–5倍。

ConcurrentQueue 和 Queue+lock 哪个更快?看场景,不是看名字
结论很直接:**在典型多线程生产者-消费者场景下(比如多个 socket 接收线程入队 + 多个工作线程出队),ConcurrentQueue 通常比手动用 lock 包裹 Queue 更快,尤其连接数 ≥ 数千时**。但这个“更快”有前提——你没滥用 Count,也没在单线程里硬套它。
为什么 ConcurrentQueue 在高并发下更胜一筹?
核心是「无锁」不等于「没开销」,而是把竞争从「阻塞等待锁」换成了「快速重试 + CAS 原子操作」。当多个线程同时 Enqueue 或 TryDequeue 时:
-
Queue+lock:所有争抢锁的线程会进入阻塞态,触发上下文切换,CPU 缓存失效,开销陡增 -
ConcurrentQueue:线程用SpinWait短暂自旋重试,多数操作在用户态完成,避免了内核态切换 - 实测数据(100 万次操作):
ConcurrentQueue入队约45 ms,Queue+lock约210 ms;出队同理,快 4–5 倍
什么时候 Queue+lock 反而更优?
别迷信“线程安全=一定更快”。以下情况,手写 lock 的 Queue 更稳、更快:
- 你需要频繁读取
Count属性(例如做限流、监控或 while 循环批量消费)——ConcurrentQueue.Count是 O(n) 遍历所有 segment,**在大吞吐下会成瓶颈** - 你的“多线程”其实是伪并发:比如只有 1 个生产者 + 1 个消费者,且处理逻辑极轻(几条指令),此时
lock的简单性反而胜过ConcurrentQueue的原子操作开销 - 你已在临界区做大量工作(比如解包 + 数据校验 + DB 写入),那锁的占比已很小,换
ConcurrentQueue带来的收益微乎其微
一个真实案例:某 Socket 服务在压测中发现 ConcurrentQueue.Count 占 CPU 12%,改用 lock + Queue + 自增计数器后,吞吐提升 18%。
怎么选?三步判断法
不用猜,按顺序问自己三个问题:
- 是否真有 ≥2 个线程**同时入队**,或 ≥2 个线程**同时出队**?→ 否:用
Queue;是:继续 - 是否需要在循环中高频访问
Count,或依赖精确长度做控制逻辑?→ 是:优先Queue+lock+ 手动计数;否:继续 - 单次入/出队操作耗时是否 byte[] 引用,不做解析)?→ 是:
ConcurrentQueue更合适;否(如要 JSON 反序列化):两者差异收敛,可任选,但ConcurrentQueue代码更干净
Socket 编程里最常见的是「多接收线程入队 + 单工作线程出队」,这种混合模式下,ConcurrentQueue 仍是首选——只要别在 while (!queue.IsEmpty) { ... } 里反复调 Count 就行。











