System.Threading.Interlocked 提供原子操作方法,在硬體層面保證操作不可分割,無需鎖即可實現線程安全的基本數值運算,效能遠優於鎖。
| 方法 | 說明 | 適用型別 |
|---|---|---|
Increment(ref int) | 原子遞增,返回新值 | int, long |
Decrement(ref int) | 原子遞減,返回新值 | int, long |
Add(ref int, int) | 原子加法,返回新值 | int, long |
Exchange(ref T, T) | 原子交換,返回舊值 | int, long, float, double, object, pointer |
CompareExchange(ref T, T, T) | 原子比較交換(CAS),返回舊值 | 同上 |
Read(ref long) | 原子讀取 64 位整數(32 位系統需此方法) | long |
using System;
using System.Threading;
class CounterDemo
{
static int count = 0;
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] = new Thread(IncrementCount);
threads[i].Start();
}
foreach (var t in threads) t.Join();
Console.WriteLine("最終計數: {0} (預期 100000)", count);
}
static void IncrementCount()
{
for (int i = 0; i < 10000; i++)
{
Interlocked.Increment(ref count);
// 等同於:Interlocked.Add(ref count, 1);
}
}
}
using System;
using System.Threading;
public class LockFreeStack<T>
{
private sealed class Node
{
public T Value;
public Node Next;
public Node(T value) { Value = value; }
}
private Node head = null;
public void Push(T item)
{
Node newNode = new Node(item);
Node oldHead;
do
{
oldHead = head;
newNode.Next = oldHead;
} while (Interlocked.CompareExchange(ref head, newNode, oldHead) != oldHead);
}
public bool TryPop(out T item)
{
Node oldHead;
do
{
oldHead = head;
if (oldHead == null)
{
item = default(T);
return false;
}
} while (Interlocked.CompareExchange(ref head, oldHead.Next, oldHead) != oldHead);
item = oldHead.Value;
return true;
}
}
// 簡單計數:Interlocked 勝出(無核心轉換、無上下文切換)
// 複雜邏輯/多變數:需用 lock 或 Monitor
// 64 位讀寫在 32 位系統:必須用 Interlocked.Read/Exchange
CompareExchange 是無鎖演算法核心(CAS),理解其語意至關重要。Thread.SpinWait 或改用鎖。Volatile 類別配合記憶體屏障,更精細控制可見性。(原文包含三張圖片,展示 Interlocked 方法結構、CAS 運作流程、無鎖堆疊示意)