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

多Task下参数降至阈值1后仍被修改,如何修复?

问题根源
  1. 线程竞争:多个Task同时读取param,判断param>1为真后,都会执行减0.1操作。哪怕param已经是1.1,多线程同时操作会直接把它降到0.9以下。
  2. 无效延迟:原代码中Task.Delay(100)未使用await,延迟根本不生效,线程会立即执行减操作,进一步加剧竞争。
  3. 非原子操作:判断param>1和执行param -=0.1是两个独立步骤,中间无同步,多个线程可插入执行,导致错误。
修复方案

核心思路:用锁保证对param的原子操作,修正异步逻辑,优化取消机制

修复后代码

class Program
{
    static decimal param = 100;
    static readonly object _lock = new object();
    static CancellationTokenSource _cts = new CancellationTokenSource();
    static CancellationToken _token;

    static async Task Main(string[] args)
    {
        int taskCount = 16;
        _token = _cts.Token;

        Console.WriteLine("Start Param = {0}", param);
        Console.WriteLine("Tasks Count = {0}", taskCount);

        var tasks = Enumerable.Range(0, taskCount)
            .Select(_ => Task.Run(DecrementAsync, _token))
            .ToList();

        await Task.WhenAll(tasks);

        Console.WriteLine("Result = {0}", param);
        Console.Read();
    }

    private static async Task DecrementAsync()
    {
        while (!_token.IsCancellationRequested)
        {
            bool canDecrement = false;

            // 锁内判断是否允许减操作
            lock (_lock)
            {
                if (param > 1)
                {
                    canDecrement = true;
                }
                else
                {
                    _cts.Cancel();
                    return;
                }
            }

            if (canDecrement)
            {
                await Task.Delay(100, _token);

                // 锁内执行减操作,再次检查避免延迟期间参数已达阈值
                lock (_lock)
                {
                    if (param > 1)
                    {
                        param -= 0.1m;
                        // 减完立即检查,触发取消
                        if (param <= 1)
                        {
                            _cts.Cancel();
                        }
                    }
                }
            }
        }
    }
}

关键修复点

  • 锁机制:所有对param的读写操作都在lock块内完成,确保同一时刻只有一个线程能操作该变量,彻底消除竞争条件。
  • 异步修正:将Decrementation改为async Task方法,用await Task.Delay(100, _token)实现正确的100ms延迟,同时支持取消延迟。
  • 双重检查:延迟前后分别判断param状态,避免延迟期间其他线程已将参数降到阈值以下,导致无效减操作。
  • 取消优化:参数达到阈值时立即触发取消令牌,让所有Task尽快终止,避免不必要的循环。

效果验证

修复后无论多少个Task并发执行,param最终都会精确等于1,不会出现低于1的情况。

内容的提问来源于stack exchange,提问作者Сергей

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:33:34