傳統多執行緒同步靠 lock、Monitor、Mutex,開發者需手動管理:
STM (Software Transactional Memory) 提供資料庫風格的 **ACID 事務語意** 給記憶體內物件,由執行階段自動處理鎖、版本控制、回滾。
// 傳統寫法:手動鎖 + 手動回滾
void Transfer(Account from, Account to, int amount)
{
lock (from) lock (to) // 死鎖風險:需固定鎖順序
{
from.Debit(amount);
to.Credit(amount); // 若拋出例外,from 已扣款需手動補回
}
}
// STM.NET 寫法:宣告式事務
void Transfer(Account from, Account to, int amount)
{
Atomic.Do(() => {
from.Debit(amount);
to.Credit(amount);
}); // 自動原子性、隔離性、失敗回滾
}
try/catch(AtomicMarkerException) 標記事務區塊 (IL 無原生 atomic 區塊)。支援 System.Transactions 整合,可與 SQL Server、MSMQ 等資源管理員協同:
using (var scope = new TransactionScope())
{
Atomic.Do(() => {
// 記憶體物件操作
account.Balance += 100;
// 資料庫操作 (自動登記到相同事務)
db.ExecuteNonQuery("UPDATE Accounts SET Balance += 100 WHERE Id=1");
});
scope.Complete();
}
| API/屬性 | 用途 |
|---|---|
Atomic.Do(Action) | 執行原子區塊 (委派語法) |
Atomic.DoAfterCommit(Action<CommitContext>) | Commit 後執行非事務動作 (如寫 Log、發送郵件) |
Atomic.DoWithCompensation(Action, Action<AbortContext>) | 提供補償邏輯 (Abort 時執行) |
[AtomicSupported] | 方法/類別支援事務內呼叫 (預設) |
[AtomicRequired] | **僅能**在事務內呼叫 (編譯期/執行期強制) |
[AtomicNotSupported] | 禁止在事務內呼叫 (如 Console.WriteLine) |
TransactionalOperation | 基類:實作自訂資源管理員 (OnCommit/OnAbort) |
public class TxAppender : TransactionalOperation
{
private TextWriter _writer;
private List<string> _buffer = new List<string>();
public TxAppender(TextWriter writer) { _writer = writer; }
[AtomicRequired]
public void Append(string line)
{
OnOperation(); // 登記到目前事務
try { _buffer.Add(line); }
catch { FailOperation(); throw; }
}
protected override void OnCommit()
{
foreach (var line in _buffer) _writer.WriteLine(line);
_buffer.Clear();
}
protected override void OnAbort() { _buffer.Clear(); }
}
// 使用方式
Atomic.Do(() => {
tracer.Append("Step 1: Balance=" + balance);
balance += 100;
tracer.Append("Step 2: Balance=" + balance);
}); // 若中途失敗,Log 不會寫入
| 場景 | 傳統痛點 | STM.NET 效益 |
|---|---|---|
| 複雜物件圖更新 | 多層巢狀 lock、死鎖難除錯 | 宣告式事務、自動隔離 |
| UI 精靈/對話框取消 | 需手動記錄舊值、回滾 | Atomic.Do 包裹,取消即 Abort |
| 單元測試隔離 | 測試殘留資料污染後續測試 | 每測試一事務,結束自動回滾 |
| 領域模型屬性設定 | 部分更新可見、驗證失敗回滾複雜 | Atomic 包裹 setter,全有或全無 |
app.config 需指定運行階段版本:
<requiredRuntime version="v4.0.20506" />
TransactionalOperation。Intel TSX (Transactional Synchronization Extensions)、IBM PowerTM 等 CPU 指令集開始支援硬體交易記憶體,未來 STM.NET 可無縫受益於硬體加速,效能差距將大幅縮小。
STM.NET 將資料庫 ACID 事務模型帶入記憶體程式設計,**以宣告式取代命令式同步**,大幅降低多執行緒正確性的認知負擔。雖屬早期實驗,但其架構思想 (JIT 插桩、陰影副本、資源管理員抽象) 深刻影響了後續 .NET 並發模型 (如 System.Threading.Tasks.Dataflow、ImmutableCollections)。值得每位 .NET 進階開發者研究其原理與應用邊界。