C# Semaphore 信號量 鎖 簡單理解


信號量(Semaphore)

Semaphore 一般譯作 信號量,它也是一種線程同步工具,主要用於多個線程對共享資源進行並行操作的一種工具類。它代表了一種許可的概念,是否允許多線程對同一資源進行操作的許可,使用 Semaphore 可以控制並發訪問資源的線程個數。


Semaphore 的使用場景

1、主要用於流量控制,比如數據庫連接,同時使用的數據庫連接會有數量限制,數據庫連接不能超過一定的數量,當連接到達了限制數量后,后面的線程只能排隊等前面的線程釋放數據庫連接后才能獲得數據庫連接。
2、 信號量:是進程間(線程間)同步用的,一個進程(線程)完成了某一個動作就通過信號量告訴別的進程(線程),別的進程(線程)再進行某些動作。有二值和多值信號量之分。

它與的互斥鎖區別是 互斥鎖:是線程間互斥用的,一個線程占用了某一個共享資源,那么別的線程就無法訪問,直到這個線程離開,其他的線程才開始可以使用這個共享資源。可以把互斥鎖看成二值信號量。  

引發的問題

信號量存在的優先級翻轉問題

優先級反轉,是指在使用信號量時,可能會出現的這樣一種不合理的現象,即:

高優先級任務被低優先級任務阻塞,導致高優先級任務遲遲得不到調度。但其他中等優先級的任務卻能搶到CPU資源。-- 從現象上來看,好像是中優先級的任務比高優先級任務具有更高的優先權。

具體來說:當高優先級任務正等待信號量(此信號量被一個低優先級任務擁有着)的時候,一個介於兩個任務優先之間的中等優先級任務開始執行——這就會導致一個高優先級任務在等待一個低優先級任務,而低優先級任務卻無法執行類似死鎖的情形發生。

主要方法

Semaphore(1, 4):默認運行信號量之后就可以釋放一條線程進入臨界資源。手動設置Release的一次最大個數是4條線程,臨界區最大的線程數是4.當一次釋放的線程超過等待的資源數就會報錯

WaitOne()阻塞線程,等燈來
Release(N) 同時放行條線程進入資源區,最大不能超過初始化設定的maximumCount
Close()釋放所有

使用方式1

有10個線程,同時只執行4條線程,每完成一個就Release一個,等待中的就補上去

 

 代碼如下:

該代碼會正常執行完成,並且釋放所有線程,因為初始化話new Semaphore(1, 4)時候已經設置默認釋放一條線程,這條線程執行完成后road.Release();又釋放下一條。依次釋放完所有線程。
 
Semaphore road = new Semaphore(1, 4);
for(int i = 0; i < 10; i++)
{
    new Thread(obj =>
    {
        int se = (int)obj;
        Console.WriteLine(se);
        road.WaitOne();

        Console.WriteLine("release{0}",obj);
        road.Release();//該線程執行完畢,后再釋放一個線程
    }

    ).Start(i);



}
Thread.Sleep(1000);
//該代碼會正常執行完成,並且釋放說有線程,因為初始化話new Semaphore(1, 4)時候已經設置默認釋放一條線程,這條線程執行完成后road.Release();又釋放下一條。依次釋放完所有線程。

 另外,信號量是內核對象可以再多個進程中使用。可以給信號量設置一個名稱,這個名稱是操作系統可見的,因此,可以使用這些信號量來協調跨進程邊界的資源使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Semaphore2
{
    class Program
    {
        static void Main(string[] args)
        {
            Semaphore seamphore = new Semaphore(5, 5, "SemaphoreExample");

            seamphore.WaitOne();
            Console.WriteLine("Seamphore 1");
            seamphore.WaitOne();
            Console.WriteLine("Seamphore 2");
            seamphore.WaitOne();
            Console.WriteLine("Seamphore 3");

            Console.ReadLine();
            seamphore.Release(3);
        }
    }
}

復制代碼

 運行兩個這樣的程序,你將看到這樣的結果,在第二個運行的示例中,會將線程阻塞在第三個信號量

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM