在C#开发中,Lazy<T> 是一个非常实用的泛型类,用于实现延迟初始化(Lazy Initialization)。尤其在处理资源密集型对象或需要按需加载的场景下,它能显著提升程序性能。但当涉及多线程环境时,开发者常常对 Lazy<T> 的线程安全性产生疑问。本文将从零开始,详细讲解 C# 中 Lazy<T> 的线程安全机制,并通过示例代码验证其行为,帮助你彻底掌握这一重要概念。

Lazy<T> 是 .NET Framework 4.0 引入的一个类,用于封装一个值,该值在首次访问时才被创建。这种“懒加载”模式可以避免在对象构造时进行不必要的计算或资源分配。
基本用法如下:
var lazyValue = new Lazy<int>(() => { Console.WriteLine("正在初始化..."); return 42;});Console.WriteLine(lazyValue.IsValueCreated); // FalseConsole.WriteLine(lazyValue.Value); // 输出:正在初始化... \n 42Console.WriteLine(lazyValue.IsValueCreated); // True很多人误以为所有 Lazy<T> 实例都是线程安全的,其实不然。它的线程安全性取决于构造时指定的 LazyThreadSafetyMode 参数。该枚举有三种模式:
当你使用无参构造函数 new Lazy<T>(Func<T>) 时,默认采用 ExecutionAndPublication 模式,因此是线程安全的。
下面我们通过一个多线程测试程序,来验证不同模式下的行为。
using System;using System.Threading;using System.Threading.Tasks;class Program{ static void Main() { // 默认模式:ExecutionAndPublication(线程安全) var lazySafe = new Lazy<string>(() => { Thread.Sleep(100); // 模拟耗时操作 Console.WriteLine($"线程 {Thread.CurrentThread.ManagedThreadId} 正在初始化"); return Guid.NewGuid().ToString(); }); // 启动多个任务并发访问 var tasks = new Task[5]; for (int i = 0; i < 5; i++) { tasks[i] = Task.Run(() => { string value = lazySafe.Value; Console.WriteLine($"线程 {Thread.CurrentThread.ManagedThreadId} 获取到值: {value.Substring(0, 8)}..."); }); } Task.WaitAll(tasks); Console.WriteLine("\n所有任务完成,观察是否只有一个线程执行了初始化。"); }}运行结果通常如下:
线程 4 正在初始化线程 4 获取到值: d1a2b3c4...线程 5 获取到值: d1a2b3c4...线程 6 获取到值: d1a2b3c4...线程 7 获取到值: d1a2b3c4...线程 8 获取到值: d1a2b3c4...所有任务完成,观察是否只有一个线程执行了初始化。可以看到,尽管有5个线程同时访问 lazySafe.Value,但只有线程4执行了初始化逻辑,其余线程直接获取了已创建的值。这证明了默认模式下的 C# Lazy<T> 线程安全机制是有效的。
LazyThreadSafetyMode.None 提升性能。PublicationOnly。ExecutionAndPublication 模式,确保 .NET Lazy类教程 中强调的安全性。Lazy<T> 是 C# 中实现延迟加载的强大工具。其线程安全性并非自动保证,而是由构造参数决定。默认情况下(即使用 new Lazy<T>(Func<T>)),它采用 ExecutionAndPublication 模式,是完全线程安全的,非常适合 C#多线程编程 场景。
掌握 Lazy初始化 的原理和线程安全机制,不仅能写出更高效的代码,还能避免潜在的并发问题。希望这篇 C# Lazy<T>线程安全 教程能帮助你打下坚实基础!
本文由主机测评网于2025-12-12发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025126591.html