国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#并行編程-線程同步原語

2019-11-17 02:56:21
字體:
來源:轉載
供稿:網友

C#并行編程-線程同步原語

菜鳥學習并行編程,參考《C#并行編程高級教程.PDF》,如有錯誤,歡迎指正。

目錄

  • C#并行編程-相關概念

  • C#并行編程-Parallel

  • C#并行編程-Task

  • C#并行編程-并發集合

  • C#并行編程-線程同步原語

  • C#并行編程-PLINQ:聲明式數據并行

背景

有時候必須訪問變量、實例、方法、屬性或者結構體,而這些并沒有準備好用于并發訪問,或者有時候需要執行部分代碼,而這些代碼必須單獨運行,這是不得不通過將任務分解的方式讓它們獨立運行。

當任務和線程要訪問共享的數據和資源的時候,您必須添加顯示的同步,或者使用原子操作或鎖。

之前的.NET Framework提供了昂貴的鎖機制以及遺留的多線程模型,新的數據結構允許細粒度的并發和并行化,并且降低一定必要的開銷,這些數據結構稱為輕量級同步原語。

這些數據結構在關鍵場合下能夠提供更好的性能,因為它們能夠避免昂貴的鎖機制,如果在等待時間不短的情況下使用它們,這些原語會增加額外的開銷。

如果您需要特定的執行順序,可以通過添加顯示同步來實現。

同步原語

.NET Framework 4在現在的System.Threading命名空間中提供了6個同步原語,通過這個命名空間可以訪問遺留的線程類、類型和枚舉,還提供了新的基于任務的編程模型及特定情形緊密相關的數據結構

Barrier 使多個任務能夠采用并行方式依據某種算法在多個階段中協同工作 通過屏障

CountdownEvent 表示在計數變為0時處于有信號狀態的同步基元 通過信號機制

ManualResetEventSlim允許很多任務等待直到另一個任務手工發出事件句柄,當預計等待時間很短的時候,ManualResetEventSlim 的性能比對應的重量級ManualResetEvent的性能要高。通過信號機制

SemaphoreSlim 限制對可同時訪問資源或資源池的線程數,比對應的Semaphore性能要高 通過信號機制

SpinLock 提供一個相互排斥鎖基元,在該基元中,嘗試獲得鎖的線程將在重復檢查的循環中等待,直至該鎖變為可用為止。

SpinWait 提供對基于自旋的等待的支持。

通過屏障同步并發任務 Barrier

當在需要一組任務并行地運行一連串的階段,但是每一個階段都要等待其他任務完成前一階段之后才能開始時,您可以通過使用Barrier類的實例來同步這一類協同工作,通過屏障

下面貼代碼方便大家理解,如有問題,請指正,詳情見注釋:

    class PRogram    {        private static Task[] _CookTasks { get; set; }        private static Barrier _barrier { get; set; }        /*獲取當前計算機處理器數*/        private static int _particpants = Environment.ProcessorCount;        /*  coder:釋迦苦僧           *  代碼中 展示煮飯的步驟   1.打水  2.淘米 3.放入鍋中 4.蓋上鍋蓋 5.生火煮飯          */        static void Main(string[] args)        {            Console.WriteLine("定義{0}個人煮飯3次", _particpants);            _CookTasks = new Task[_particpants];            _barrier = new Barrier(_particpants, (barrier) =>            {                Console.WriteLine("當前階段:{0}", barrier.CurrentPhaseNumber);            });            Stopwatch swTask1 = new Stopwatch();            swTask1.Start();            /*定義N個人*/            for (int cook_person = 0; cook_person < _particpants; cook_person++)            {                _CookTasks[cook_person] = Task.Factory.StartNew((num) =>                {                    int index = Convert.ToInt32(num);                    /*每個人煮3次飯*/                    for (int cook_count = 0; cook_count < 3; cook_count++)                    {                        CookStepTask1(index, cook_count);                        CookStepTask2(index, cook_count);                        CookStepTask3(index, cook_count);                        CookStepTask4(index, cook_count);                        CookStepTask5(index, cook_count);                    }                }, cook_person);            }            /*ContinueWhenAll 提供一組任務完成后 延續方法*/            var finalTask = Task.Factory.ContinueWhenAll(_CookTasks, (tasks) =>            {                /*等待任務完成*/                Task.WaitAll(_CookTasks);                swTask1.Stop();                Console.WriteLine("采用并發 {1}個人煮3次飯耗時:{0}", swTask1.ElapsedMilliseconds, _particpants);                /*釋放資源*/                _barrier.Dispose();            });            Thread.Sleep(4000);            Stopwatch swTask = new Stopwatch();            swTask.Start();            /*定義N個人*/            for (int cook_person = 0; cook_person < _particpants; cook_person++)            {                /*每個人煮3次飯*/                for (int cook_count = 0; cook_count < 3; cook_count++)                {                    CookStep1(cook_person, cook_count); CookStep2(cook_person, cook_count); CookStep3(cook_person, cook_count); CookStep4(cook_person, cook_count); CookStep5(cook_person, cook_count);                }            }            swTask.Stop();            Console.WriteLine("不采用并發 {1}個人煮3次飯耗時:{0}", swTask.ElapsedMilliseconds, _particpants);            Thread.Sleep(2000);            Console.ReadLine();        }        /*1.打水*/        private static void CookStepTask1(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 打水... 耗時2分鐘", pesron_index, index);            Thread.Sleep(200);            /*存在線程暫停 所以需要將 _barrier.SignalAndWait();放在方法中 */            _barrier.SignalAndWait();        }        /*2.淘米*/        private static void CookStepTask2(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 淘米... 耗時3分鐘", pesron_index, index);            Thread.Sleep(300);            /*存在線程暫停 所以需要將 _barrier.SignalAndWait();放在方法中 */            _barrier.SignalAndWait();        }        /*3.放入鍋中*/        private static void CookStepTask3(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 放入鍋中... 耗時1分鐘", pesron_index, index);            Thread.Sleep(100);            /*存在線程暫停 所以需要將 _barrier.SignalAndWait();放在方法中 */            _barrier.SignalAndWait();        }        /*4.蓋上鍋蓋*/        private static void CookStepTask4(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 蓋上鍋蓋... 耗時1分鐘", pesron_index, index);            Thread.Sleep(100);            /*存在線程暫停 所以需要將 _barrier.SignalAndWait();放在方法中 */            _barrier.SignalAndWait();        }        /*5.生火煮飯*/        private static void CookStepTask5(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次  生火煮飯... 耗時30分鐘", pesron_index, index);            Thread.Sleep(500);            /*存在線程暫停 所以需要將 _barrier.SignalAndWait();放在方法中 */            _barrier.SignalAndWait();        }        /*1.打水*/        private static void CookStep1(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 打水... 耗時2分鐘", pesron_index, index);            Thread.Sleep(200);        }        /*2.淘米*/        private static void CookStep2(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 淘米... 耗時3分鐘", pesron_index, index);            Thread.Sleep(300);        }        /*3.放入鍋中*/        private static void CookStep3(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 放入鍋中... 耗時1分鐘", pesron_index, index);            Thread.Sleep(100);        }        /*4.蓋上鍋蓋*/        private static void CookStep4(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 蓋上鍋蓋... 耗時1分鐘", pesron_index, index);            Thread.Sleep(100);        }        /*5.生火煮飯*/        private static void CookStep5(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次  生火煮飯... 耗時30分鐘", pesron_index, index);            Thread.Sleep(500);        }    }    class Product    {        public string Name { get; set; }        public string Category { get; set; }        public int SellPrice { get; set; }    }
View Code

如代碼所示,在串行代碼中,雖然任務是有序進行,但是等待的時間很長,因為只是在一個處理器下進行處理,如下圖所示:

而采用并發處理中,使用Barrier,不僅保證了任務的有序進行,還在性能損耗上得到了最大程度的降低,如下圖

ContinueWhenAll 提供一組任務完成后的延續方法

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 庄河市| 安多县| 沁阳市| 绥滨县| 迭部县| 同心县| 丹江口市| 北流市| 蓝山县| 宁晋县| 安阳县| 吴堡县| 五常市| 南安市| 乌海市| 黎川县| 大安市| 阿拉善左旗| 陆河县| 安义县| 斗六市| 公安县| 阿拉善右旗| 桐梓县| 娄底市| 凤阳县| 景泰县| 长泰县| 平塘县| 磴口县| 腾冲县| 和顺县| 且末县| 英山县| 威海市| 敖汉旗| 松滋市| 乐业县| 柯坪县| 南陵县| 沅江市|