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

多线程环境下如何让指定代码仅执行一次?现有锁方案失效求助

问题原因分析
  • 你的锁对象locker和状态标识IsModelLoaded是实例级成员:如果每个线程都创建了独立的类实例,那么每个实例都会持有独立的锁和状态标识,锁完全不会生效,自然每个线程都会执行初始化逻辑,这是你遇到的最核心问题。
  • 你尝试的[MethodImpl(MethodImplOptions.Synchronized)]如果修饰实例方法,默认锁的是当前实例,多实例场景下同样会失效,且该特性锁粒度不可控,本身就不推荐使用。
  • Release模式下失效的核心原因是你没有保证状态标识的跨线程可见性,或是多实例场景下状态完全隔离,Debug模式下的调试附加逻辑会隐形添加内存屏障,所以会碰巧生效。
修复方案

方案1:静态锁+双重检查锁定(适合全局仅一次初始化的场景)

把锁对象和状态标识改为静态成员,保证所有类实例共享同一个锁和状态,同时增加外层无锁判断提升性能:

// 静态成员,全局所有实例共享
private static readonly object _locker = new object();
private static bool _isInitialized = false;

public void Initialize()
{
    // 外层无锁判断,避免每次调用都抢锁
    if (_isInitialized) return;
    lock (_locker)
    {
        // 抢到锁后二次判断,避免多线程同时进入外层判断后重复执行
        if (_isInitialized) return;
        Console.WriteLine("PrintMsg");
        // 环境搭建、文件夹创建等初始化逻辑写在此处
        _isInitialized = true;
    }
}

该方案完全兼容Release模式,不会出现多线程重复执行的问题。

方案2:使用.NET内置Lazy<T>(优先推荐,无手动锁出错风险)

.NET Framework 4.0+、.NET Core/.NET 5+都原生提供了Lazy<T>类,专门用于线程安全的延迟初始化,默认保证初始化逻辑仅执行一次,不需要手动处理锁和状态判断:

// 静态Lazy对象,初始化逻辑写在委托内
private static readonly Lazy<bool> _initializer = new Lazy<bool>(() =>
{
    Console.WriteLine("PrintMsg");
    // 环境搭建、文件夹创建等初始化逻辑写在此处
    return true;
}, isThreadSafe: true);

public void Initialize()
{
    // 只需访问Value属性,初始化逻辑只会在第一次访问时执行一次
    var _ = _initializer.Value;
}

该方案底层已经处理了所有线程安全和内存可见性问题,代码更简洁,不会出现手动锁的常见错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:54:05