class Counter
{
private static int _count = 0;
public static int GetNext()
{
int n = _count;
// 模擬耗時操作
_count = n + 1;
return n;
}
}
// 多線程並發調用 GetNext() 會導致返回值重複/丟失
class Counter
{
private static int _count = 0;
private static readonly object _lock = new object();
public static int GetNext()
{
lock (_lock)
{
int n = _count;
_count = n + 1;
return n;
}
}
}
// 或使用 Interlocked.Increment(ref _count) 無鎖原子操作
class Olympics
{
public static List Runners = new List();
}
class Runner
{
public FileStream Stream; // 未關閉的非托管資源
}
// 靜態列表持有 Runner → Runner 不會被 GC 回收 → FileStream 洩漏
教訓:靜態字段是 GC Root,會長期存活引用對象,必須及時清理非托管資源(實現 IDisposable、使用 using)。
// 推薦:靜態只讀字段 + 私有構造函數(CLR 保證線程安全初始化)
public sealed class Earth
{
private static readonly Earth _instance = new Earth();
private Earth() { }
public static Earth Instance => _instance;
}
// 雙重檢查鎖(舊版 .NET 可能需要 volatile,現代 .NET 不再推薦)
// 避免:嵌套類延遲初始化、Lazy<T>(除非構造極其昂貴)
using / IDisposable / SafeHandle。null,特別是事件處理器、大對象、靜態集合。IDisposable;終結器增加 GC 壓力、延遲回收、順序不定。List),減少堆碎片,提升 GC 掃描效率。ArrayPool。struct,減少堆分配與 GC 掃描。-= 防止發布者持有訂閱者導致內存洩漏。WeakReference / ConditionalWeakTable 實現可回收緩存。dotMemory、PerfView、GC.GetTotalMemory 定期檢視堆狀態。