C#vb.net中Interlocked类实现原子操作加减计算,涵盖状态切换、计数控制等常见场景

以下是 C# 中使用 int 类型结合 Interlocked 类实现原子操作的完整示例,涵盖状态切换、计数控制等常见场景:

完整代码示例csharp

using System;
using System.Threading;

/// <summary>
/// 基于整数类型的原子操作工具类(线程安全)
/// 适用于开关状态控制、计数器等场景
/// </summary>
public static class AtomicStateManager
{
    // 核心状态变量:用整数表示不同状态
    // 示例场景:0=关闭(False),1=开启(True);也可扩展为多状态(如0=未初始化,1=运行中,2=已停止)
    private static int _state = 0; 

    #region 基础状态控制(开关场景)
    /// <summary>
    /// 原子设置状态为“开启”(对应值1)
    /// </summary>
    public static void Enable()
    {
        // 直接将状态设为1,无视当前值(原子操作)
        Interlocked.Exchange(ref _state, 1);
    }

    /// <summary>
    /// 原子设置状态为“关闭”(对应值0)
    /// </summary>
    public static void Disable()
    {
        // 直接将状态设为0,无视当前值(原子操作)
        Interlocked.Exchange(ref _state, 0);
    }

    /// <summary>
    /// 原子切换状态(0→1 或 1→0)
    /// </summary>
    public static void Toggle()
    {
        // 循环尝试切换,直到成功(处理并发冲突)
        do
        {
            int currentState = _state; // 读取当前状态
            int newState = currentState == 1 ? 0 : 1; // 计算目标状态
            // 比较并交换:如果当前值仍为currentState,则更新为newState
            // 若交换失败(返回值≠currentState),则重试
        } while (Interlocked.CompareExchange(ref _state, newState, _state) != _state);
    }

    /// <summary>
    /// 原子读取当前状态是否为“开启”
    /// </summary>
    /// <returns>True=开启(1),False=关闭(0)</returns>
    public static bool IsEnabled()
    {
        // 用CompareExchange确保读取到最新值(避免CPU缓存导致的脏读)
        return Interlocked.CompareExchange(ref _state, 0, 0) == 1;
    }
    #endregion

    #region 计数器场景(原子增减)
    /// <summary>
    /// 原子递增状态值(+1)
    /// </summary>
    /// <returns>递增后的新值</returns>
    public static int Increment()
    {
        return Interlocked.Increment(ref _state);
    }

    /// <summary>
    /// 原子递减状态值(-1)
    /// </summary>
    /// <returns>递减后的新值</returns>
    public static int Decrement()
    {
        return Interlocked.Decrement(ref _state);
    }

    /// <summary>
    /// 原子读取当前计数值
    /// </summary>
    /// <returns>当前状态值</returns>
    public static int GetCount()
    {
        return Interlocked.CompareExchange(ref _state, 0, 0);
    }
    #endregion

    #region 高级场景:条件更新(仅当满足条件时修改)
    /// <summary>
    /// 仅当当前状态为“关闭”时,原子设置为“开启”
    /// </summary>
    /// <returns>True=更新成功,False=当前状态不满足条件</returns>
    public static bool EnableIfDisabled()
    {
        // 比较并交换:若当前值为0(关闭),则更新为1(开启)
        int originalValue = Interlocked.CompareExchange(ref _state, 1, 0);
        return originalValue == 0; // 若原始值为0,说明更新成功
    }

    /// <summary>
    /// 仅当当前状态为目标值时,原子更新为新值
    /// </summary>
    /// <param name="expectedValue">预期当前值</param>
    /// <param name="newValue">目标新值</param>
    /// <returns>True=更新成功,False=当前值不符预期</returns>
    public static bool UpdateIfMatch(int expectedValue, int newValue)
    {
        int originalValue = Interlocked.CompareExchange(ref _state, newValue, expectedValue);
        return originalValue == expectedValue;
    }
    #endregion
}

使用示例csharp

class Program
{
    static void Main()
    {
        // 1. 开关状态场景
        AtomicStateManager.Enable();
        Console.WriteLine($"是否开启:{AtomicStateManager.IsEnabled()}"); // 输出:True

        AtomicStateManager.Toggle();
        Console.WriteLine($"切换后是否开启:{AtomicStateManager.IsEnabled()}"); // 输出:False

        bool updateSuccess = AtomicStateManager.EnableIfDisabled();
        Console.WriteLine($"是否成功开启:{updateSuccess}"); // 输出:True
        Console.WriteLine($"当前状态:{AtomicStateManager.IsEnabled()}"); // 输出:True


        // 2. 计数器场景
        AtomicStateManager.Increment(); // 状态从1→2
        AtomicStateManager.Increment(); // 状态从2→3
        Console.WriteLine($"当前计数:{AtomicStateManager.GetCount()}"); // 输出:3

        AtomicStateManager.Decrement(); // 状态从3→2
        Console.WriteLine($"递减后计数:{AtomicStateManager.GetCount()}"); // 输出:2


        // 3. 条件更新场景
        bool conditionUpdate = AtomicStateManager.UpdateIfMatch(2, 100);
        Console.WriteLine($"条件更新是否成功:{conditionUpdate}"); // 输出:True
        Console.WriteLine($"更新后的值:{AtomicStateManager.GetCount()}"); // 输出:100
    }
}

核心原理与优势

  1. 原子性保证
    Interlocked 类的方法通过底层硬件指令实现原子操作,确保操作过程不会被其他线程打断,避免竞态条件。

  2. 性能优化
    相比 lock 等锁机制,Interlocked 操作无需上下文切换,开销更小,适合高频访问场景。

  3. 可见性保证
    所有 Interlocked 操作会强制刷新 CPU 缓存,确保所有线程看到的是最新值,避免因缓存导致的数据不一致。

  4. 灵活性扩展
    示例中用 0 和 1 表示开关状态,实际可扩展为多状态(如 0=未初始化1=运行中2=已停止),通过 UpdateIfMatch 方法实现复杂状态转换。

这种方式特别适合 IIS 等多线程环境下的全局变量控制,可有效避免并发修改导致的异常。


VB.NET的用法例子:

将布尔值转换为整数类型(如 Integer)后使用 Interlocked 类的原子操作(如递增、递减、比较交换),在多线程场景中会更直观且高效。这种方式特别适合需要 "开关状态切换" 或 "计数控制" 的场景。

以下是 VB.NET 中基于整数类型的原子操作实现,以 GetServerInfo 的状态控制为例:

实现示例:VB.NET 用整数类型模拟状态,结合原子操作

vb

Imports System.Threading

' 用整数表示状态:0=关闭(False),1=开启(True)
Private Shared _serverInfoState As Integer = 0 ' 初始状态:关闭

' 原子开启(设置为1)
Public Sub EnableServerInfo()
    Interlocked.Exchange(_serverInfoState, 1)
End Sub

' 原子关闭(设置为0)
Public Sub DisableServerInfo()
    Interlocked.Exchange(_serverInfoState, 0)
End Sub

' 原子切换状态(0→1 或 1→0)
Public Sub ToggleServerInfo()
    ' 循环尝试切换,直到成功(处理并发冲突)
    Do
        Dim currentState = _serverInfoState
        Dim newState = If(currentState = 1, 0, 1)
        ' 比较并交换:如果当前值仍为 currentState,则更新为 newState
    Loop While Interlocked.CompareExchange(_serverInfoState, newState, currentState) <> currentState
End Sub

' 原子读取当前状态
Public Function IsServerInfoEnabled() As Boolean
    ' 读取操作本身是原子的,但用 CompareExchange 确保可见性
    Return Interlocked.CompareExchange(_serverInfoState, 0, 0) = 1
End Function

' 原子递增(适合计数场景)
Public Sub IncrementCounter()
    Interlocked.Increment(_serverInfoState)
End Sub

' 原子递减(适合计数场景)
Public Sub DecrementCounter()
    Interlocked.Decrement(_serverInfoState)
End Sub

优势说明

  1. 操作直观
    用 0 和 1 对应 False 和 True,通过 Interlocked.Increment/Decrement 可直接实现计数,无需额外转换逻辑。

  2. 性能优异
    Interlocked 类的方法是底层硬件支持的原子操作,比 SyncLock 等锁机制开销更小,尤其适合高频访问的场景。

  3. 避免竞态条件

    • Exchange 确保 "设置新值" 操作的原子性,不会被其他线程打断。
    • CompareExchange 结合循环可实现 "检查 - 更新" 的原子性(如 ToggleServerInfo 方法),避免并发下的状态不一致。
  4. 可见性保证
    Interlocked 操作会强制刷新 CPU 缓存,确保所有线程看到的是最新值(避免因缓存导致的 "脏读")。

适用场景

  • 简单的开关状态(如 GetServerInfo 的启用 / 禁用)。
  • 计数器(如统计并发请求数、操作次数)。
  • 需要原子 "检查并修改" 的逻辑(如仅当状态为关闭时才开启)。

如果你的场景涉及更复杂的状态转换(如多值状态),这种整数映射方式同样适用,只需扩展数值对应的含义即可(如 0=未初始化1=运行中2=已停止)。

C# 中的 `System.Threading.Interlocked` 提供了一组用于在多线程环境中进行原子操作的方法。原子操作是指不会被其他线程中断的操作,保证了操作结果的一致性和完整性。在单个处理器核心上,这些操作通常是不可分割的,但是在多核环境下,它们会尽可能保持低级锁(Lock-free),提高性能。 以下是一些常见的 `Interlocked` 方法示例: 1. **`Interlocked.Add`**:对一个整数型的变量进行加法操作,并确保操作原子的。这对于在多线程环境中累加计数非常有用,比如递增一个计数器: ```csharp int counter = 0; Interlocked.Add(ref counter, 1); // 线程安全地将counter加1 ``` 2. **`Interlocked.Exchange`**:原子地交换两个变量的值,常用于互斥锁(Mutex)等场景: ```csharp bool lockTaken; ref bool currentLock = ref Interlocked.Exchange(ref myLock, true); if (!currentLock) { // Acquired the lock } ``` 3. **`Interlocked.Decrement`** 和 **`Interlocked.Increment`**:分别用于减一和加一操作,同样保证了原子性。 4. **`CompareExchange`**:比较并替换值,只有当目标值等于预期值时才进行替换,适用于读取-条件-写入(Read-Modify-Write)的场景。 使用 `Interlocked` 进行操作时,可以避免不必要的上下文切换和竞态条件,提高程序的性能。然而,它并不是所有情况下的万能解,对于复杂的并发问题,可能还需要配合其他的并发控制机制如 `Monitor` 或者 `lock` 语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专注VB编程开发20年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值