You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现相同参数线程串行执行、不同参数线程并行执行?

实现相同参数串行、不同参数并行的线程处理方案

问题描述

现有一段C#代码,线程方法Method1会修改传入的Class1对象,要求:

  • 同一个Class1对象的处理必须串行(不能被多个线程同时修改,避免并发冲突)
  • 不同的Class1对象可以并行处理(最大化执行效率)

同时想确认:是否需要在新建并启动线程前,逐个检查是否已有处理相同参数的线程?

原代码如下:

class Class1
{
    // something
}

private void Form1_Load(object sender, EventArgs e)
{
    List<Class1> _List = new();
            
    for (int i = 0; i < 10; i++)
    {
        _List.Add(new Class1 { });
    }
            
    for (int i = 0; i < 10; i++)
    {
        Thread _Thread = new(Method1);

        _Thread.Start(_List[new Random().Next(10)]); // 可能连续选中同一个List元素
    }
}

void Method1(object _Object)
{
    // 修改传入的_Object
}

解决方案

不需要手动逐个检查线程状态,推荐使用基于对象的专属锁+线程池的方案,既满足并发需求又避免手动管理线程的麻烦。

核心思路

  1. 为每个Class1对象分配一个专属的锁对象,确保同一对象的处理请求会排队等待,不同对象的锁互不干扰,实现细粒度并发控制。
  2. 用ConcurrentDictionary<Class1, object>存储每个对象对应的锁,它是线程安全的集合,适合多线程环境下存取锁对象。
  3. 替换手动创建Thread的方式,改用Task.Run(基于.NET线程池),比手动创建线程更高效、易管理。

修改后的代码示例

using System.Collections.Concurrent;

class Class1
{
    // 类成员
}

// 类级的线程安全锁字典,存储每个Class1对象对应的锁
private readonly ConcurrentDictionary<Class1, object> _objectLocks = new ConcurrentDictionary<Class1, object>();

private void Form1_Load(object sender, EventArgs e)
{
    List<Class1> _List = new List<Class1>();
            
    for (int i = 0; i < 10; i++)
    {
        _List.Add(new Class1());
    }
            
    // 把Random实例提到循环外,避免因系统时钟精度问题生成重复随机数
    var random = new Random();
    for (int i = 0; i < 10; i++)
    {
        var targetObj = _List[random.Next(10)];
        // 用Task.Run启动异步处理,自动利用线程池
        _ = ProcessClass1Async(targetObj);
    }
}

// 包装处理逻辑,加入锁保护
async Task ProcessClass1Async(Class1 obj)
{
    // 获取当前对象的专属锁,不存在则自动创建
    var lockObj = _objectLocks.GetOrAdd(obj, _ => new object());
    
    // 同一obj的lock块会串行执行,不同obj的lock块并行执行
    lock (lockObj)
    {
        Method1(obj);
    }
    
    // 可选:如果该obj后续不再被处理,可以移除锁对象释放内存
    // _objectLocks.TryRemove(obj, out _);
}

void Method1(Class1 _Object)
{
    // 原有的修改逻辑,现在已被lock保护,不会出现并发修改问题
}

关键说明

  • 无需手动检查线程:lock关键字会自动对同一锁对象的请求进行排队,底层已经处理了线程同步逻辑,不需要自己跟踪线程状态。
  • 锁粒度控制:每个Class1对象对应一个锁,实现了最小粒度的并发控制,既保证同一对象的串行安全,又不影响其他对象的并行处理。
  • 线程池优势:Task.Run复用线程池中的线程,避免频繁创建销毁线程的性能开销,同时.NET会自动管理线程数量,防止资源耗尽。
  • Random的坑:原代码在循环中每次新建Random,会因为系统时钟的精度问题导致生成重复的随机数,所以必须把Random实例放到循环外。

内容的提问来源于stack exchange,提问作者SHIN JaeGuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:35:29