以下是 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()}"); // 輸出:TrueAtomicStateManager.Toggle();Console.WriteLine($"切換后是否開啟:{AtomicStateManager.IsEnabled()}"); // 輸出:Falsebool updateSuccess = AtomicStateManager.EnableIfDisabled();Console.WriteLine($"是否成功開啟:{updateSuccess}"); // 輸出:TrueConsole.WriteLine($"當前狀態:{AtomicStateManager.IsEnabled()}"); // 輸出:True// 2. 計數器場景AtomicStateManager.Increment(); // 狀態從1→2AtomicStateManager.Increment(); // 狀態從2→3Console.WriteLine($"當前計數:{AtomicStateManager.GetCount()}"); // 輸出:3AtomicStateManager.Decrement(); // 狀態從3→2Console.WriteLine($"遞減后計數:{AtomicStateManager.GetCount()}"); // 輸出:2// 3. 條件更新場景bool conditionUpdate = AtomicStateManager.UpdateIfMatch(2, 100);Console.WriteLine($"條件更新是否成功:{conditionUpdate}"); // 輸出:TrueConsole.WriteLine($"更新后的值:{AtomicStateManager.GetCount()}"); // 輸出:100}
}
核心原理與優勢
-
原子性保證:
Interlocked
?類的方法通過底層硬件指令實現原子操作,確保操作過程不會被其他線程打斷,避免競態條件。 -
性能優化:
相比?lock
?等鎖機制,Interlocked
?操作無需上下文切換,開銷更小,適合高頻訪問場景。 -
可見性保證:
所有?Interlocked
?操作會強制刷新 CPU 緩存,確保所有線程看到的是最新值,避免因緩存導致的數據不一致。 -
靈活性擴展:
示例中用?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()' 循環嘗試切換,直到成功(處理并發沖突)DoDim currentState = _serverInfoStateDim newState = If(currentState = 1, 0, 1)' 比較并交換:如果當前值仍為 currentState,則更新為 newStateLoop 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
優勢說明
-
操作直觀:
用?0
?和?1
?對應?False
?和?True
,通過?Interlocked.Increment
/Decrement
?可直接實現計數,無需額外轉換邏輯。 -
性能優異:
Interlocked
?類的方法是底層硬件支持的原子操作,比?SyncLock
?等鎖機制開銷更小,尤其適合高頻訪問的場景。 -
避免競態條件:
Exchange
?確保 "設置新值" 操作的原子性,不會被其他線程打斷。CompareExchange
?結合循環可實現 "檢查 - 更新" 的原子性(如?ToggleServerInfo
?方法),避免并發下的狀態不一致。
-
可見性保證:
Interlocked
?操作會強制刷新 CPU 緩存,確保所有線程看到的是最新值(避免因緩存導致的 "臟讀")。
適用場景
- 簡單的開關狀態(如?
GetServerInfo
?的啟用 / 禁用)。 - 計數器(如統計并發請求數、操作次數)。
- 需要原子 "檢查并修改" 的邏輯(如僅當狀態為關閉時才開啟)。
如果你的場景涉及更復雜的狀態轉換(如多值狀態),這種整數映射方式同樣適用,只需擴展數值對應的含義即可(如?0=未初始化
、1=運行中
、2=已停止
)。