c# Array.Sort 是线程安全的吗

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

Array.Sort 不是线程安全的

直接回答:对同一个

Array
实例并发调用
Array.Sort
会导致未定义行为,包括数据错乱、越界异常甚至进程崩溃。.NET 官方文档明确标注
Array.Sort
的静态重载「不是线程安全的」,实例方法(如
Array.Sort<t>(T[])</t>
)同样不保证线程安全。

哪些场景会出问题

常见误用包括:

多个线程同时对同一数组对象调用
Array.Sort
一个线程在排序时,另一个线程正在读/写该数组元素(即使没调用
Sort
使用
Array.Sort
配合自定义
IComparer
,而该比较器内部访问了共享可变状态(如静态字段、缓存字典)

这类情况不会抛出明确的「线程不安全」异常,而是表现为排序结果错误、

IndexOutOfRangeException
或偶尔的
ArgumentException
(例如“array was modified”)。

如何安全地并发排序

没有银弹,但有明确可行路径:

确保每个线程操作**独立的数组副本**:
int[] original = { 3, 1, 4 };
int[] copy = (int[])original.Clone();
Array.Sort(copy); // 安全
lock
保护共享数组(仅适用于低频、小数组):
private static readonly object sortLock = new object();
lock (sortLock) { Array.Sort(sharedArray); }
改用线程安全的替代结构:如先转为
List<t></t>
并用
AsParallel().OrderBy()
(注意:这会创建新序列,不就地排序)
避免共享——从设计上让排序任务隔离,比如按业务 ID 分片,各线程处理自己分到的子数组

为什么 .NET 不让它线程安全

根本原因在于性能与语义权衡:

Array.Sort
使用的是 introsort(快排 + 堆排 + 插入排序混合),过程中需要频繁交换原数组元素,加锁会严重拖慢速度
数组本身是引用类型,但其内容修改是裸内存操作,.NET 不可能为每次索引赋值自动加锁 线程安全的责任被明确划归调用方——这是 BCL(基础类库)的一贯设计哲学:核心类型默认不承担同步开销

真正容易被忽略的是:即使你只读数组,只要另一个线程正在调用

Array.Sort
,读操作也未必看到一致状态——因为排序过程中的中间态是公开可见的。

相关推荐