信息发布→ 登录 注册 退出

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

发布时间:2026-01-06

点击量:
Array.Sort 不是线程安全的:并发调用同一数组实例会导致数据错乱、越界异常或崩溃;官方明确标注其静态和实例方法均不保证线程安全,需通过独立副本、lock 或并行LINQ等方式保障安全。

Array.Sort 不是线程安全的

直接回答:对同一个 Array 实例并发调用 Array.Sort 会导致未定义行为,包括数据错乱、越界异常甚至进程崩溃。.NET 官方文档明确标注 Array.Sort 的静态重载「不是线程安全的」,实例方法(如 Array.Sort(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 并用 AsParallel().OrderBy()(注意:这会创建新序列,不就地排序)
  • 避免共享——从设计上让排序任务隔离,比如按业务 ID 分片,各线程处理自己分到的子数组

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

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

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

真正容易被忽略的是:即使你只读数组,只要另一个线程正在调用 Array.Sort,读操作也未必看到一致状态——因为排序过程中的中间态是公开可见的。

标签:# 对象  # 让它  # 自定义  # 这类  # 不承担  # 适用于  # 多个  # 这是  # 加锁  # 过程中  # 的是  # linq  # c#  # 并发  # 线程  # 引用类型  #   # 插入排序  # sort  # Array  # red  # 为什么  # .net  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!