C#實現(xiàn)讀寫分離的五種方法小結(jié)
1. 使用 ReaderWriterLockSlim
.NET 提供的高性能讀寫鎖,支持以下模式:
讀模式(Read Lock):允許多個線程同時讀取。
寫模式(Write Lock):獨占鎖,其他所有讀寫操作都會被阻塞。
using System.Threading;
public class ReadWriteExample
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private int _sharedData = 0;
// 讀操作
public int ReadData()
{
_lock.EnterReadLock();
try
{
return _sharedData;
}
finally
{
_lock.ExitReadLock();
}
}
// 寫操作
public void WriteData(int value)
{
_lock.EnterWriteLock();
try
{
_sharedData = value;
}
finally
{
_lock.ExitWriteLock();
}
}
}優(yōu)點:
細粒度控制讀寫操作。
支持遞歸鎖和超時機制。
缺點:
需要手動管理鎖的獲取和釋放。
2. 使用 Concurrent 并發(fā)集合
.NET 的 System.Collections.Concurrent 命名空間提供了線程安全的集合類,內(nèi)部已實現(xiàn)讀寫分離邏輯:
ConcurrentDictionary<TKey, TValue>ConcurrentQueue<T>ConcurrentBag<T>
using System.Collections.Concurrent;
public class ConcurrentExample
{
private readonly ConcurrentDictionary<string, int> _data = new();
// 讀操作(無鎖)
public int GetValue(string key)
{
return _data.TryGetValue(key, out int value) ? value : -1;
}
// 寫操作(內(nèi)部使用細粒度鎖)
public void UpdateValue(string key, int value)
{
_data.AddOrUpdate(key, value, (k, oldValue) => value);
}
}優(yōu)點:
開箱即用,無需手動管理鎖。
高性能,適合高頻讀寫場景。
缺點:
靈活性較低,僅適用于預(yù)定義的集合類型。
3. 基于 volatile 和內(nèi)存屏障(Memory Barrier)
適用于簡單變量的讀寫分離,通過 volatile 關(guān)鍵字確保內(nèi)存可見性:
public class VolatileExample
{
private volatile bool _flag = false;
private int _data = 0;
// 讀操作(無鎖)
public int ReadData()
{
if (_flag)
return _data;
return -1;
}
// 寫操作(需要同步)
public void WriteData(int value)
{
Interlocked.Exchange(ref _data, value); // 原子寫入
Volatile.Write(ref _flag, true); // 確保寫入對其他線程可見
}
}優(yōu)點:
輕量級,適合簡單場景。
無鎖讀操作。
缺點:
僅適用于簡單類型(如
int、bool)。需要手動處理內(nèi)存可見性。
4. 數(shù)據(jù)庫讀寫分離
在數(shù)據(jù)庫層面實現(xiàn)讀寫分離(如主從架構(gòu)),C# 代碼通過不同連接字符串路由請求:
public class DatabaseRouter
{
private static readonly string ReadConnectionString = "Server=ReadServer;...";
private static readonly string WriteConnectionString = "Server=WriteServer;...";
public IDbConnection GetReadConnection() =>
new SqlConnection(ReadConnectionString);
public IDbConnection GetWriteConnection() =>
new SqlConnection(WriteConnectionString);
}
// 使用示例
using (var readConn = DatabaseRouter.GetReadConnection())
{
// 執(zhí)行查詢操作
}
using (var writeConn = DatabaseRouter.GetWriteConnection())
{
// 執(zhí)行更新操作
}優(yōu)點:
直接利用數(shù)據(jù)庫主從復(fù)制特性。
減輕主庫壓力。
缺點:
需要數(shù)據(jù)庫支持主從同步。
可能存在數(shù)據(jù)同步延遲。
5. 基于不可變數(shù)據(jù)(Immutable Data)
通過每次修改生成新對象實現(xiàn)無鎖讀?。ㄈ缡褂?nbsp;ImmutableList<T> 或自定義不可變類型):
using System.Collections.Immutable;
public class ImmutableExample
{
private ImmutableList<int> _data = ImmutableList<int>.Empty;
// 讀操作(無鎖)
public int GetItem(int index)
{
return _data[index];
}
// 寫操作(原子替換)
public void AddItem(int item)
{
ImmutableInterlocked.Update(ref _data, list => list.Add(item));
}
}優(yōu)點:
完全無鎖讀取。
天然線程安全。
缺點:
頻繁修改可能產(chǎn)生內(nèi)存壓力。
選擇策略
| 場景 | 推薦方案 |
|---|---|
| 細粒度代碼級讀寫控制 | ReaderWriterLockSlim |
| 高頻并發(fā)集合操作 | ConcurrentDictionary 等并發(fā)集合 |
| 簡單變量的讀寫 | volatile + Interlocked |
| 數(shù)據(jù)庫訪問分離 | 主從架構(gòu) + 連接路由 |
| 高頻讀、低頻寫 | 不可變數(shù)據(jù)(如 ImmutableList) |
注意事項
避免死鎖:確保鎖的獲取和釋放成對出現(xiàn)(用
try-finally塊)。性能權(quán)衡:讀寫鎖適合讀多寫少場景,寫頻繁時可能不如普通鎖高效。
數(shù)據(jù)一致性:數(shù)據(jù)庫讀寫分離時需處理主從同步延遲問題。
到此這篇關(guān)于C#實現(xiàn)讀寫分離的五種方法小結(jié)的文章就介紹到這了,更多相關(guān)C#讀寫分離內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#中IDispose接口的實現(xiàn)及為何這么實現(xiàn)詳解
這篇文章主要給大家介紹了關(guān)于C#中IDispose接口的實現(xiàn)及為何這么實現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05

