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

如何解决C#中跨类多线程共享counter变量的竞态条件问题?

问题分析与解决方案

核心问题

  1. 主线程useValue等待工作线程updateValue的信号时,若工作线程未启动或updateValue未执行,会无限阻塞。
  2. updateValue依赖的SomeClassType val无法在useValue所在类访问,导致无法触发工作线程执行更新逻辑。

解决方案思路

  • 主动触发工作线程启动,并传递所需参数。
  • 给等待操作设置超时,避免主线程无限阻塞。
  • 保证跨线程变量的可见性,消除竞态条件。
  • 可选:用更现代的异步Task模型替代传统的AutoResetEvent,简化线程管理。

方案一:完善AutoResetEvent的使用逻辑

工作线程类调整(支持接收参数并启动)

public class WorkerClass
{
    // 用实例级别的事件,避免多实例冲突
    private readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
    // 用volatile保证线程可见性,避免CPU缓存读取旧值
    private volatile int _counter = 0;

    public int Counter => _counter;
    public AutoResetEvent UpdateCompletedEvent => _autoResetEvent;

    // 对外提供启动工作线程并执行更新的方法
    public void StartUpdate(SomeClassType val)
    {
        // 将更新逻辑放到工作线程执行
        Thread workerThread = new Thread(() => UpdateValue(val));
        workerThread.Start();
    }

    private void UpdateValue(SomeClassType val)
    {
        if (val.id)
        {
            _counter = 2;
        }
        // 发送更新完成信号
        _autoResetEvent.Set();
    }
}

主线程useValue实现

public class MainThreadClass
{
    protected void UseValue()
    {
        // 1. 准备工作线程需要的参数实例
        SomeClassType val = new SomeClassType();
        val.id = true; // 设置触发更新的条件

        // 2. 初始化工作类并启动更新线程
        WorkerClass worker = new WorkerClass();
        worker.StartUpdate(val);

        // 3. 等待更新完成,设置5秒超时防止无限阻塞
        bool isUpdated = worker.UpdateCompletedEvent.WaitOne(TimeSpan.FromSeconds(5));
        
        if (isUpdated)
        {
            // 使用更新后的counter执行业务操作
            int updatedCounter = worker.Counter;
            // ...
        }
        else
        {
            // 处理超时场景,比如日志记录、重试逻辑
            // ...
        }
    }
}

方案二:用Task异步模型(推荐,.NET 4.5+)

无需手动管理线程和事件,异步等待更简洁安全:

public class WorkerClass
{
    private volatile int _counter = 0;
    public int Counter => _counter;

    // 异步更新方法,自动放到线程池执行
    public async Task UpdateValueAsync(SomeClassType val)
    {
        // 模拟耗时操作,替换为实际业务逻辑
        await Task.Run(() =>
        {
            if (val.id)
            {
                _counter = 2;
            }
        });
    }
}

public class MainThreadClass
{
    // 用async修饰方法,支持await等待更新完成
    protected async void UseValue()
    {
        SomeClassType val = new SomeClassType { id = true };
        WorkerClass worker = new WorkerClass();

        // 等待更新完成
        await worker.UpdateValueAsync(val);

        // 直接使用更新后的counter执行业务操作
        int updatedCounter = worker.Counter;
        // ...
    }
}

关键注意点

  • 线程可见性:跨线程访问的变量(如counter)需用volatile修饰,或用Interlocked类操作,避免CPU缓存导致的读取旧值问题。
  • 避免静态同步对象:静态AutoResetEvent会在多实例场景下导致信号混乱,优先用实例级别的同步对象。
  • 超时机制:任何线程等待操作都要设置超时,防止主线程无限阻塞影响程序响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:12:09