c# ConcurrentQueue 和 Queue 加 lock 哪个性能好

来源:这里教程网 时间:2026-02-21 17:38:36 作者:

ConcurrentQueue 和 Queue+lock 哪个更快?看场景,不是看名字

结论很直接:**在典型多线程生产者-消费者场景下(比如多个 socket 接收线程入队 + 多个工作线程出队),ConcurrentQueue 通常比手动用

lock
包裹
Queue<t></t>
更快,尤其连接数 ≥ 数千时**。但这个“更快”有前提——你没滥用
Count
,也没在单线程里硬套它。

为什么 ConcurrentQueue 在高并发下更胜一筹?

核心是「无锁」不等于「没开销」,而是把竞争从「阻塞等待锁」换成了「快速重试 + CAS 原子操作」。当多个线程同时

Enqueue
TryDequeue
时:

Queue<t></t>
+
lock
:所有争抢锁的线程会进入阻塞态,触发上下文切换,CPU 缓存失效,开销陡增
ConcurrentQueue<t></t>
:线程用
SpinWait
短暂自旋重试,多数操作在用户态完成,避免了内核态切换
实测数据(100 万次操作):
ConcurrentQueue
入队约
45 ms
Queue+lock
210 ms
;出队同理,快 4–5 倍

什么时候 Queue+lock 反而更优?

别迷信“线程安全=一定更快”。以下情况,手写

lock
Queue<t></t>
更稳、更快:

你需要频繁读取
Count
属性(例如做限流、监控或 while 循环批量消费)——
ConcurrentQueue.Count
是 O(n) 遍历所有 segment,**在大吞吐下会成瓶颈**
你的“多线程”其实是伪并发:比如只有 1 个生产者 + 1 个消费者,且处理逻辑极轻(几条指令),此时
lock
的简单性反而胜过
ConcurrentQueue
的原子操作开销
你已在临界区做大量工作(比如解包 + 数据校验 + DB 写入),那锁的占比已很小,换
ConcurrentQueue
带来的收益微乎其微

一个真实案例:某 Socket 服务在压测中发现

ConcurrentQueue.Count
占 CPU 12%,改用
lock
+
Queue<t></t>
+ 自增计数器后,吞吐提升 18%。

怎么选?三步判断法

不用猜,按顺序问自己三个问题:

是否真有 ≥2 个线程**同时入队**,或 ≥2 个线程**同时出队**?→ 否:用
Queue<t></t>
;是:继续
是否需要在循环中高频访问
Count
,或依赖精确长度做控制逻辑?→ 是:优先
Queue<t></t>
+
lock
+ 手动计数;否:继续
单次入/出队操作耗时是否 byte[] 引用,不做解析)?→ 是:
ConcurrentQueue
更合适;否(如要 JSON 反序列化):两者差异收敛,可任选,但
ConcurrentQueue
代码更干净

Socket 编程里最常见的是「多接收线程入队 + 单工作线程出队」,这种混合模式下,

ConcurrentQueue
仍是首选——只要别在
while (!queue.IsEmpty) { ... }
里反复调
Count
就行。

相关推荐