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

C#多线程中count变量非100倍数?加锁后仍异常求解

多线程场景下count值不符合预期的问题分析与解决

问题重现

以下是出现问题的C#代码:

private static readonly object ThreadKey = new object();

private void PlayVideo()
{
    int count = 0;

    for (int y = 1; y < 1000; y++)
    {
        lock(ThreadKey)
        {
            count++;
            if ((count % 100) == 0)
            {
                Task.Run(() => TestTh(count));
            }
        }
     
    }
}
private void TestTh(int count)
{
    // 发现count并非100的倍数
    System.IO.File.WriteAllText(@"D:\USER\Desktop\Myfolder\" + count.ToString()+".txt", count.ToString());
}

问题原因

这不是锁的问题,核心原因是闭包捕获的是变量的引用而非当前值:

  • 当Task.Run(() => TestTh(count))被调用时,lambda表达式捕获的是count变量的引用,而非此时count的具体数值。
  • 锁块仅保证count++和条件判断是原子操作,但Task的执行是异步的,会在后续某个时间点运行。在Task执行前,for循环会继续执行,count会被多次自增,导致Task最终读取的count值已经不是触发条件时的100倍数。

解决方案

在锁块内创建临时变量存储当前的count值,让lambda捕获这个临时变量(临时变量的值在当前锁块内是固定的,不会被后续循环修改):

修改后的代码:

private static readonly object ThreadKey = new object();

private void PlayVideo()
{
    int count = 0;

    for (int y = 1; y < 1000; y++)
    {
        lock(ThreadKey)
        {
            count++;
            if ((count % 100) == 0)
            {
                // 创建临时变量存储当前count值
                int currentCount = count;
                Task.Run(() => TestTh(currentCount));
            }
        }
     
    }
}
private void TestTh(int count)
{
    System.IO.File.WriteAllText(@"D:\USER\Desktop\Myfolder\" + count.ToString()+".txt", count.ToString());
}

这样每个Task都会拿到触发条件时的准确count值,保证写入文件的数值都是100的倍数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:15:14