源码片段
private static int _builderAlreadyAllocated;
...
private static bool IsFirstContainerBuilder()
{
// First container will start with a value of 0, we will try and set it to 1;
// if the value is 0, it means it's the first builder.
return Interlocked.CompareExchange(ref _builderAlreadyAllocated, 1, 0) == 0;
}
Interlocked.CompareExchange 方法签名
public static int CompareExchange(ref int location, int value, int comparand)
| 参数 |
说明 |
| location |
目标变量(_builderAlreadyAllocated)的引用 |
| value |
要设置的新值(1) |
| comparand |
要比较的值(0) |
执行逻辑
- 读取 location(即 _builderAlreadyAllocated)的当前值
- 比较当前值是否等于comparand (即0)
- 如果相等,则将 value(即 1)写入 location,并返回原始值
- 如果不相等,则不做任何修改,并返回当前值
性能优势
- Interlocked.CompareExchange 是硬件级别的原子指令,不需要操作系统的内核对象(如 Mutex)或用户模式锁(如 lock)。
- 在初始化完成后,后续检查只是一个简单的整型比较,开销极小
.NET内置的替代方案:Lazy
private static readonly Lazy<IContainer> _container =
new Lazy<IContainer>(() =>
{
var builder = new ContainerBuilder();
// ... 注册服务
return builder.Build();
});
public static IContainer Container => _container.Value;
优点
- 线程安全:默认使用 LazyThreadSafetyMode.ExecutionAndPublication,保证只执行一次
- 代码简洁:不需要手写任何锁或原子操作
- 延迟执行:只有首次访问 Value 时才触发构建
- 异常处理:如果构建失败,异常会被包装并重新抛出