最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#多線程系列之資源池限制

 更新時間:2022年02月13日 15:25:28   作者:癡者工良  
這篇文章介紹了C#多線程的資源池限制,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

Semaphore、SemaphoreSlim 類

兩者都可以限制同時訪問某一資源或資源池的線程數(shù)。

這里先不扯理論,我們從案例入手,通過示例代碼,慢慢深入了解。

Semaphore 類

這里,先列出 Semaphore 類常用的 API。

其構(gòu)造函數(shù)如下:

構(gòu)造函數(shù)說明
Semaphore(Int32, Int32)初始化 Semaphore 類的新實例,并指定初始入口數(shù)和最大并發(fā)入口數(shù)。
Semaphore(Int32, Int32, String)初始化 Semaphore 類的新實例,并指定初始入口數(shù)和最大并發(fā)入口數(shù),根據(jù)需要指定系統(tǒng)信號燈對象的名稱。
Semaphore(Int32, Int32, String, Boolean)初始化 Semaphore 類的新實例,并指定初始入口數(shù)和最大并發(fā)入口數(shù),還可以選擇指定系統(tǒng)信號量對象的名稱,以及指定一個變量來接收指示是否創(chuàng)建了新系統(tǒng)信號量的值。

Semaphore 使用純粹的內(nèi)核時間(kernel-time)方式(等待時間很短),并且支持在不同的進程間同步線程(像Mutex)。

Semaphore 常用方法如下:

方法說明
Close()釋放由當(dāng)前 WaitHandle占用的所有資源。
OpenExisting(String)打開指定名稱為信號量(如果已經(jīng)存在)。
Release()退出信號量并返回前一個計數(shù)。
Release(Int32)以指定的次數(shù)退出信號量并返回前一個計數(shù)。
TryOpenExisting(String, Semaphore)打開指定名稱為信號量(如果已經(jīng)存在),并返回指示操作是否成功的值。
WaitOne()阻止當(dāng)前線程,直到當(dāng)前 WaitHandle 收到信號。
WaitOne(Int32)阻止當(dāng)前線程,直到當(dāng)前 WaitHandle 收到信號,同時使用 32 位帶符號整數(shù)指定時間間隔(以毫秒為單位)。
WaitOne(Int32, Boolean)阻止當(dāng)前線程,直到當(dāng)前的 WaitHandle 收到信號為止,同時使用 32 位帶符號整數(shù)指定時間間隔,并指定是否在等待之前退出同步域。
WaitOne(TimeSpan)阻止當(dāng)前線程,直到當(dāng)前實例收到信號,同時使用 TimeSpan 指定時間間隔。
WaitOne(TimeSpan, Boolean)阻止當(dāng)前線程,直到當(dāng)前實例收到信號為止,同時使用 TimeSpan 指定時間間隔,并指定是否在等待之前退出同步域。

示例

我們來直接寫代碼,這里使用 《原子操作 Interlocked》 中的示例,現(xiàn)在我們要求,采用多個線程執(zhí)行計算,但是只允許最多三個線程同時執(zhí)行運行。

使用 Semaphore ,有四個個步驟:

new 實例化 Semaphore,并設(shè)置最大線程數(shù)、初始化時可進入線程數(shù);

使用 .WaitOne(); 獲取進入權(quán)限(在獲得進入權(quán)限前,線程處于阻塞狀態(tài))。

離開時使用 Release() 釋放占用。

Close() 釋放Semaphore 對象。

《原子操作 Interlocked》 中的示例改進如下:

    class Program
    {
        // 求和
        private static int sum = 0;
        private static Semaphore _pool;

        // 判斷十個線程是否結(jié)束了。
        private static int isComplete = 0;
        // 第一個程序
        static void Main(string[] args)
        {
            Console.WriteLine("執(zhí)行程序");

            // 設(shè)置允許最大三個線程進入資源池
            // 一開始設(shè)置為0,就是初始化時允許幾個線程進入
            // 這里設(shè)置為0,后面按下按鍵時,可以放通三個線程
            _pool = new Semaphore(0, 3);
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(AddOne));
                thread.Start(i + 1);
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("任意按下鍵(不要按關(guān)機鍵),可以打開資源池");
            Console.ForegroundColor = ConsoleColor.White;
            Console.ReadKey();

            // 準(zhǔn)許三個線程進入
            _pool.Release(3);

            // 這里沒有任何意義,就單純?yōu)榱搜菔静榭唇Y(jié)果。
            // 等待所有線程完成任務(wù)
            while (true)
            {
                if (isComplete >= 10)
                    break;
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("sum = " + sum);

            // 釋放池
            _pool.Close();
            
        }

        public static void AddOne(object n)
        {
            Console.WriteLine($"    線程{(int)n}啟動,進入隊列");
            // 進入隊列等待
            _pool.WaitOne();
            Console.WriteLine($"第{(int)n}個線程進入資源池");
            // 進入資源池
            for (int i = 0; i < 10; i++)
            {
                Interlocked.Add(ref sum, 1);
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }
            // 解除占用的資源池
            _pool.Release();
            isComplete += 1;
            Console.WriteLine($"                     第{(int)n}個線程退出資源池");
        }
    }

看著代碼有點多,快去運行一下,看看結(jié)果。

示例說明

實例化 Semaphore 使用了new Semaphore(0,3); ,其構(gòu)造函數(shù)原型為

public Semaphore(int initialCount, int maximumCount);

initialCount 表示一開始允許幾個進程進入資源池,如果設(shè)置為0,所有線程都不能進入,要一直等資源池放通。

maximumCount 表示最大允許幾個線程進入資源池。

Release() 表示退出信號量并返回前一個計數(shù)。這個計數(shù)指的是資源池還可以進入多少個線程。

可以看一下下面的示例:

        private static Semaphore _pool;
        static void Main(string[] args)
        {
            _pool = new Semaphore(0, 5);
            _pool.Release(5);
            new Thread(AddOne).Start();
            Thread.Sleep(TimeSpan.FromSeconds(10));
            _pool.Close();
        }

        public static void AddOne()
        {
            _pool.WaitOne();
            Thread.Sleep(1000);
            int count = _pool.Release();
            Console.WriteLine("在此線程退出資源池前,資源池還有多少線程可以進入?" + count);
        }

信號量

前面我們學(xué)習(xí)到 Mutex,這個類是全局操作系統(tǒng)起作用的。我們從 Mutex 和 Semphore 中,也看到了 信號量這個東西。

信號量分為兩種類型:本地信號量和命名系統(tǒng)信號量。

  • 命名系統(tǒng)信號量在整個操作系統(tǒng)中均可見,可用于同步進程的活動。
  • 局部信號量僅存在于進程內(nèi)。

當(dāng) name 為 null 或者為空時,Mutex 的信號量時局部信號量,否則 Mutex 的信號量是命名系統(tǒng)信號量。

Semaphore 的話,也是兩種情況都有。

如果使用接受名稱的構(gòu)造函數(shù)創(chuàng)建 Semaphor 對象,則該對象將與該名稱的操作系統(tǒng)信號量關(guān)聯(lián)。

兩個構(gòu)造函數(shù):

Semaphore(Int32, Int32, String)
Semaphore(Int32, Int32, String, Boolean)

上面的構(gòu)造函數(shù)可以創(chuàng)建多個表示同一命名系統(tǒng)信號量的 Semaphore 對象,并可以使用 OpenExisting 方法打開現(xiàn)有的已命名系統(tǒng)信號量。

我們上面使用的示例就是局部信號量,進程中引用本地 Semaphore 對象的所有線程都可以使用。 每個 Semaphore 對象都是單獨的本地信號量。

SemaphoreSlim類

SemaphoreSlim 跟 Semaphore 有啥關(guān)系?

微軟文檔:

SemaphoreSlim 表示對可同時訪問資源或資源池的線程數(shù)加以限制的 Semaphore 的輕量替代。

SemaphoreSlim 不使用信號量,不支持進程間同步,只能在進程內(nèi)使用。

它有兩個構(gòu)造函數(shù):

構(gòu)造函數(shù)說明
SemaphoreSlim(Int32)初始化 SemaphoreSlim 類的新實例,以指定可同時授予的請求的初始數(shù)量。
SemaphoreSlim(Int32, Int32)初始化 SemaphoreSlim 類的新實例,同時指定可同時授予的請求的初始數(shù)量和最大數(shù)量。

示例

我們改造一下前面 Semaphore 中的示例:

    class Program
    {
        // 求和
        private static int sum = 0;
        private static SemaphoreSlim _pool;

        // 判斷十個線程是否結(jié)束了。
        private static int isComplete = 0;
        static void Main(string[] args)
        {
            Console.WriteLine("執(zhí)行程序");

            // 設(shè)置允許最大三個線程進入資源池
            // 一開始設(shè)置為0,就是初始化時允許幾個線程進入
            // 這里設(shè)置為0,后面按下按鍵時,可以放通三個線程
            _pool = new SemaphoreSlim(0, 3);
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(AddOne));
                thread.Start(i + 1);
            }

            Console.WriteLine("任意按下鍵(不要按關(guān)機鍵),可以打開資源池");
            Console.ReadKey();
            // 
            _pool.Release(3);

            // 這里沒有任何意義,就單純?yōu)榱搜菔静榭唇Y(jié)果。
            // 等待所有線程完成任務(wù)
            while (true)
            {
                if (isComplete >= 10)
                    break;
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("sum = " + sum);
            // 釋放池
        }

        public static void AddOne(object n)
        {
            Console.WriteLine($"    線程{(int)n}啟動,進入隊列");
            // 進入隊列等待
            _pool.Wait();
            Console.WriteLine($"第{(int)n}個線程進入資源池");
            // 進入資源池
            for (int i = 0; i < 10; i++)
            {
                Interlocked.Add(ref sum, 1);
                Thread.Sleep(TimeSpan.FromMilliseconds(200));
            }
            // 解除占用的資源池
            _pool.Release();
            isComplete += 1;
            Console.WriteLine($"                     第{(int)n}個線程退出資源池");
        }
    }

SemaphoreSlim 不需要 Close()。

兩者在代碼上的區(qū)別是就這么簡單。

區(qū)別

如果使用下面的構(gòu)造函數(shù)實例化 Semaphor(參數(shù)name不能為空),那么創(chuàng)建的對象在整個操作系統(tǒng)內(nèi)都有效。

public Semaphore (int initialCount, int maximumCount, string name);

Semaphorslim 則只在進程內(nèi)內(nèi)有效。

SemaphoreSlim 類不會對 Wait、WaitAsync 和 Release 方法的調(diào)用強制執(zhí)行線程或任務(wù)標(biāo)識。

而 Semaphor 類,會對此進行嚴(yán)格監(jiān)控,如果對應(yīng)調(diào)用數(shù)量不一致,會出現(xiàn)異常。

此外,如果使用 SemaphoreSlim(Int32 maximumCount) 構(gòu)造函數(shù)來實例化 SemaphoreSlim 對象,獲取其 CurrentCount 屬性,其值可能會大于 maximumCount。 編程人員應(yīng)負(fù)責(zé)確保調(diào)用一個 Wait 或 WaitAsync 方法,便調(diào)用一個 Release。

這就好像筆筒里面的筆,沒有監(jiān)控,使用這使用完畢后,都應(yīng)該將筆放進去。如果原先有10支筆,每次使用不放進去,或者將別的地方的筆放進去,那么最后數(shù)量就不是10了。

到此這篇關(guān)于C#多線程系列之資源池限制的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#中重載與重寫區(qū)別分析

    C#中重載與重寫區(qū)別分析

    這篇文章主要為大家詳細(xì)介紹了C#中重載與重寫的區(qū)別,感興趣的小伙伴們可以參考一下
    2016-02-02
  • C#操作DataGridView獲取或設(shè)置當(dāng)前單元格的內(nèi)容

    C#操作DataGridView獲取或設(shè)置當(dāng)前單元格的內(nèi)容

    這篇文章介紹了C#操作DataGridView獲取或設(shè)置當(dāng)前單元格的內(nèi)容,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • 【C#基礎(chǔ)】Substring截取字符串的方法小結(jié)(推薦)

    【C#基礎(chǔ)】Substring截取字符串的方法小結(jié)(推薦)

    這篇文章主要介紹了Substring截取字符串方法小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • C#計算矩陣的秩實例分析

    C#計算矩陣的秩實例分析

    這篇文章主要介紹了C#計算矩陣的秩實現(xiàn)方法,以實例形式較為詳細(xì)的分析了C#計算矩陣秩的原理與實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • C#實現(xiàn)Socket通信的解決方法

    C#實現(xiàn)Socket通信的解決方法

    這篇文章主要介紹了C#實現(xiàn)Socket通信的解決方法,需要的朋友可以參考下
    2014-07-07
  • 輸出的文本實現(xiàn)對齊的方法(超簡單)

    輸出的文本實現(xiàn)對齊的方法(超簡單)

    下面小編就為大家分享一篇c#輸出的文本實現(xiàn)對齊的方法,特別簡單!希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • c# 線程定時器 System.Threading.Timer的使用

    c# 線程定時器 System.Threading.Timer的使用

    本文主要介紹了c# 線程定時器 System.Threading.Timer的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • c#消息提示框messagebox的詳解及使用

    c#消息提示框messagebox的詳解及使用

    這篇文章主要介紹了c#消息提示框messagebox的詳解及使用的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • C#使用foreach語句簡單遍歷數(shù)組的方法

    C#使用foreach語句簡單遍歷數(shù)組的方法

    這篇文章主要介紹了C#使用foreach語句簡單遍歷數(shù)組的方法,涉及C#中foreach語句的使用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • C#獲取DICOM圖像像素的像素值的代碼詳解

    C#獲取DICOM圖像像素的像素值的代碼詳解

    DICOM即醫(yī)學(xué)數(shù)字成像和通信,是醫(yī)學(xué)圖像和相關(guān)信息的國際標(biāo)準(zhǔn)(ISO 12052),它定義了質(zhì)量能滿足臨床需要的可用于數(shù)據(jù)交換的醫(yī)學(xué)圖像格式,這篇文章主要介紹了C#獲取DICOM圖像像素的像素值的方法,需要的朋友可以參考下
    2024-07-07

最新評論

浦东新区| 桐梓县| 鄂温| 乳源| 铜陵市| 北安市| 利川市| 理塘县| 德阳市| 宣威市| 静乐县| 灵石县| 二连浩特市| 平罗县| 兴海县| 台湾省| 宝兴县| 昌都县| 达孜县| 嵩明县| 福安市| 江源县| 南华县| 溆浦县| 玉山县| 历史| 从化市| 孝昌县| 东安县| 柘城县| 南开区| 虞城县| 洛南县| 四川省| 苗栗县| 绥芬河市| 左云县| 子洲县| 芮城县| 宝应县| 中西区|