本文主要講解.Net基於ReaderWriterLockSlim講解讀寫鎖


基礎概念

  • 讀寫鎖是一個具有特殊用途的執行緒鎖,適用於頻繁讀取且讀取需要一定時間的場景,共享資源的讀取操作通常是可以同時執行的,
  • 普通的互斥鎖不管是獲取還是修改操作無法同時執行,如果多個執行緒為了讀取操作而獲取互斥鎖,那麼同一時間只有一個執行緒可以執行讀取操作,
  • 頻繁讀取的場景下回對吞吐量造成影響
  • 讀寫鎖把鎖分為讀取鎖和寫入鎖,執行緒可以根據對共享資源的操作型別獲取讀取鎖還是寫入鎖,讀取鎖可以被多個執行緒同時獲取,寫入鎖不可以被多個執行緒
  • 同時獲取,且讀取鎖和寫入鎖不可以被不同的線同時獲取,
操作 讀取鎖狀態 寫入鎖狀態 獲取鎖是否需要等待
獲取讀取鎖 未獲取 未獲取 無需等待
獲取讀取鎖 已被其他執行緒獲取 未獲取 無需等待
獲取讀取鎖 未獲取 已被其他執行緒獲取 需要等待其他執行緒釋放
獲取寫入鎖 未獲取 未獲取 無需等待
獲取寫入鎖 已被其他執行緒獲取 未獲取 需要等待其他執行緒釋放
獲取寫入鎖 未獲取 已被其他執行緒獲取 需要等待其他執行緒釋放

程式碼示例

 class Program
{
static void Main(string[] args)
{
var c = ReadWriteLockDemo.GetValue("value", x =>
{
Console.WriteLine(x);
return x;
}); Console.WriteLine("結束了");
Console.WriteLine($@"獲取到的結果為:{c}");
}
}
public static class ReadWriteLockSimpleDemo
{
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); private static int _countA = 0; public static int _countB = 0; /// <summary>
/// 增加
/// </summary>
public static void IncrementCounters()
{
_lock.EnterWriteLock();
try
{
++_countA;
++_countB;
}
finally
{ _lock.ExitWriteLock();
}
} /// <summary>
/// 獲取
/// </summary>
/// <param name="countA"></param>
/// <param name="countB"></param>
public static void GetCounters(ref int countA, ref int countB)
{
_lock.EnterReadLock();
try
{
countA = _countA;
countB = _countB;
}
finally
{
_lock.ExitReadLock();
}
}
}

升級版


public static class ReadWriteLockDemo
{
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static Dictionary<string, string> _dict = new Dictionary<string, string>(); public static string GetValue(string key, Func<string, string> factory)
{
_lock.EnterUpgradeableReadLock();
try
{
//值已生成時可以直接返回
if (_dict.TryGetValue(key, out var value))
{
return value;
}
//獲取(升級到)寫入鎖
_lock.EnterWriteLock();
try
{
//再次判斷值是否已生成
if (!_dict.TryGetValue(key, out value))
{
value = factory(key);
_dict.Add(key, value);
}
return value;
}
finally
{
//釋放寫入鎖
_lock.ExitWriteLock();
}
}
finally
{
//釋放讀取鎖
_lock.ExitUpgradeableReadLock();
}
}
}

本文基於.Net Core底層入門總結內容

如有哪裡講得不是很明白或是有錯誤,歡迎指正

如您喜歡的話不妨點個贊收藏一下吧