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

如何在Parallel.ForEach中实现共享互锁变量?

在Parallel.ForEach中安全共享计数变量的实现方法

在并行循环中直接共享普通变量会引发竞态条件(多个线程同时读写导致计数不准确),必须用线程安全的机制来处理。以下是几种可靠的实现方式:

1. 使用Interlocked类(轻量级推荐)

Interlocked类提供原子操作,能确保计数的增减在多线程下不会被打断,性能比锁更优。

修改你的代码如下:

List<string> bob = new List<string>();
bob.Add("hey");
bob.Add("asdasf");
bob.Add("dfghfghd");
bob.Add("rtertdf");
bob.Add("2535dfgd");
bob.Add("sdfsdfzcxv");
bob.Add("sfgsdgsdfh");
bob.Add("23454567");
bob.Add("fgjuoiyhji");
bob.Add("ghjnbvdfg");
bob.Add("fghdtu5645");
bob.Add("565yhfhgh");
bob.Add("ewqrwy77684");
bob.Add("nbndrthw2");

int currentCount = 0;

Parallel.ForEach(bob, peer =>
{
    // 原子递增并获取最新值
    int count = Interlocked.Increment(ref currentCount);
    Console.WriteLine(peer + " : " + count);
});

2. 使用lock语句(适合复杂操作)

如果需要对共享变量执行更复杂的逻辑(不止简单递增),可以用lock确保同一时间只有一个线程访问变量:

List<string> bob = new List<string>();
bob.Add("hey");
bob.Add("asdasf");
// 省略其他Add操作

int currentCount = 0;
object lockObj = new object(); // 锁对象必须是引用类型

Parallel.ForEach(bob, peer =>
{
    lock (lockObj)
    {
        currentCount++;
        Console.WriteLine(peer + " : " + currentCount);
    }
});

3. 使用Parallel.ForEach的本地状态重载(减少竞争)

当迭代次数非常多时,让每个线程维护自己的本地计数,最后合并到全局变量,能大幅减少线程间的竞争:

List<string> bob = new List<string>();
bob.Add("hey");
bob.Add("asdasf");
// 省略其他Add操作

int totalCount = 0;

Parallel.ForEach(bob, 
    // 初始化每个线程的本地状态
    () => 0,
    // 每个迭代执行的逻辑,更新本地计数
    (peer, state, localCount) =>
    {
        localCount++;
        Console.WriteLine(peer + " : " + localCount); // 此处为线程本地计数,若需全局计数可在合并后输出
        return localCount;
    },
    // 每个线程结束后,合并本地计数到全局变量
    localCount => Interlocked.Add(ref totalCount, localCount)
);

Console.WriteLine("总计数: " + totalCount);

注意:如果需要全局递增的序号,第一种Interlocked方案最直接;如果追求性能,第三种本地状态方案更适合大规模迭代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 04:24:16