一文帶你了解.Net訊號量

本文主要講解.Net基於Semaphore帶大家了解訊號量
訊號量舉例
大家去銀行去銀行取錢,互斥鎖管理的時一個櫃檯是否正在處理業務,而訊號量管理的是整個櫃檯是否正在處理業務,每當有一個櫃檯處理完成之後,A大堂經理則進行叫號喊下一位進行處理業務,B大堂經理則對進來的客戶進行接待,當櫃檯全部都在辦理業務時,新來的辦理業務者則需要進行等待
訊號量的基礎概念
訊號量是一個具有特殊用途的執行緒同步對象,相比互斥鎖只有兩個狀態(未被獲取/已被獲取),訊號量內部使用一個數值記錄可用的數量,每個執行緒可以通過增加和減少數量兩個操作進行同步。當執行減少數量操作時,如果減少的數量大於現有的數量,則執行緒需要進入等待狀態,知道其他執行緒執行增加數量操作後數量不少於減少的數量為止。
訊號量和互斥鎖的區別
互斥鎖釋放鎖的執行緒必須是獲取鎖的執行緒,而訊號量增加數量和減少數量可以是不通
作業系統的區別
- windows系統中訊號量對象從CreateSemaphoreEx函數創建,減少數量是通過WaitForMultipObjectsEx函數,增加數量時通過ReleaseSemaphoehanshu, 由於介面限制,減少數量時只能減少1,而增加數量則可以使用自定義數量。
- linux系統中有Net Core的內部結構模擬實現。
- 和System.Threading.Mutex一樣,Semaphore可以進行使用參數命名來控制跨進程使用(注意,只支援window平台,其他平台使用會拋出異常)
程式碼事例
public class Program
{
//第一個參數代表初始數量,第二個參數代表最大數量,第三個參數代表跨進程名稱(本文未演示)
private static readonly Semaphore _sema = new(0, 10);
/// <summary>
/// 執行函數
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
for (var i = 0; i < 6; ++i)
{
var thread = new Thread(Work);
thread.Start();
}
while (true)
{
//執行增加數量,增加值為5
_sema.Release(5);
Thread.Sleep(1000 * 10);
}
}
public static void Work()
{
while (true)
{
//執行減少操作,減少值為1
_sema.WaitOne();
Console.WriteLine($"當前時間為:{DateTime.Now:yyyy-MM-dd HH:mm:ss:fff}");
Console.WriteLine($"當前執行緒Id為:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine("************************");
}
}
}
輕量訊號量
輕量訊號量不支援跨進程使用,如果不需要使用跨進程,可以使用SemaphoreSlim來代替Semaphore
public class SemaphoreSlimDemo
{
private static readonly SemaphoreSlim _semaphoreSlim = new(0, 10);
public static void Wrok()
{
while (true)
{
_semaphoreSlim.Wait();
System.Console.WriteLine("do work");
}
}
/// <summary>
/// 執行函數
/// </summary>
public static void Run()
{
for (var i = 0; i < 6; i++)
{
var thread = new Thread(Wrok)
{
IsBackground = true
};
thread.Start();
}
while (true)
{
_semaphoreSlim.Release(2);
Thread.Sleep(1000);
}
}
}
本文基於.Net Core底層入門總結內容
如有哪裡講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧🙂