麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C#并行編程-線程同步原語(yǔ)

2019-11-17 02:56:21
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

C#并行編程-線程同步原語(yǔ)

菜鳥學(xué)習(xí)并行編程,參考《C#并行編程高級(jí)教程.PDF》,如有錯(cuò)誤,歡迎指正。

目錄

  • C#并行編程-相關(guān)概念

  • C#并行編程-Parallel

  • C#并行編程-Task

  • C#并行編程-并發(fā)集合

  • C#并行編程-線程同步原語(yǔ)

  • C#并行編程-PLINQ:聲明式數(shù)據(jù)并行

背景

有時(shí)候必須訪問變量、實(shí)例、方法、屬性或者結(jié)構(gòu)體,而這些并沒有準(zhǔn)備好用于并發(fā)訪問,或者有時(shí)候需要執(zhí)行部分代碼,而這些代碼必須單獨(dú)運(yùn)行,這是不得不通過將任務(wù)分解的方式讓它們獨(dú)立運(yùn)行。

當(dāng)任務(wù)和線程要訪問共享的數(shù)據(jù)和資源的時(shí)候,您必須添加顯示的同步,或者使用原子操作或鎖。

之前的.NET Framework提供了昂貴的鎖機(jī)制以及遺留的多線程模型,新的數(shù)據(jù)結(jié)構(gòu)允許細(xì)粒度的并發(fā)和并行化,并且降低一定必要的開銷,這些數(shù)據(jù)結(jié)構(gòu)稱為輕量級(jí)同步原語(yǔ)。

這些數(shù)據(jù)結(jié)構(gòu)在關(guān)鍵場(chǎng)合下能夠提供更好的性能,因?yàn)樗鼈兡軌虮苊獍嘿F的鎖機(jī)制,如果在等待時(shí)間不短的情況下使用它們,這些原語(yǔ)會(huì)增加額外的開銷。

如果您需要特定的執(zhí)行順序,可以通過添加顯示同步來(lái)實(shí)現(xiàn)。

同步原語(yǔ)

.NET Framework 4在現(xiàn)在的System.Threading命名空間中提供了6個(gè)同步原語(yǔ),通過這個(gè)命名空間可以訪問遺留的線程類、類型和枚舉,還提供了新的基于任務(wù)的編程模型及特定情形緊密相關(guān)的數(shù)據(jù)結(jié)構(gòu)

Barrier 使多個(gè)任務(wù)能夠采用并行方式依據(jù)某種算法在多個(gè)階段中協(xié)同工作 通過屏障

CountdownEvent 表示在計(jì)數(shù)變?yōu)?時(shí)處于有信號(hào)狀態(tài)的同步基元 通過信號(hào)機(jī)制

ManualResetEventSlim允許很多任務(wù)等待直到另一個(gè)任務(wù)手工發(fā)出事件句柄,當(dāng)預(yù)計(jì)等待時(shí)間很短的時(shí)候,ManualResetEventSlim 的性能比對(duì)應(yīng)的重量級(jí)ManualResetEvent的性能要高。通過信號(hào)機(jī)制

SemaphoreSlim 限制對(duì)可同時(shí)訪問資源或資源池的線程數(shù),比對(duì)應(yīng)的Semaphore性能要高 通過信號(hào)機(jī)制

SpinLock 提供一個(gè)相互排斥鎖基元,在該基元中,嘗試獲得鎖的線程將在重復(fù)檢查的循環(huán)中等待,直至該鎖變?yōu)榭捎脼橹埂?/p>

SpinWait 提供對(duì)基于自旋的等待的支持。

通過屏障同步并發(fā)任務(wù) Barrier

當(dāng)在需要一組任務(wù)并行地運(yùn)行一連串的階段,但是每一個(gè)階段都要等待其他任務(wù)完成前一階段之后才能開始時(shí),您可以通過使用Barrier類的實(shí)例來(lái)同步這一類協(xié)同工作,通過屏障

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

    class PRogram    {        private static Task[] _CookTasks { get; set; }        private static Barrier _barrier { get; set; }        /*獲取當(dāng)前計(jì)算機(jī)處理器數(shù)*/        private static int _particpants = Environment.ProcessorCount;        /*  coder:釋迦苦僧           *  代碼中 展示煮飯的步驟   1.打水  2.淘米 3.放入鍋中 4.蓋上鍋蓋 5.生火煮飯          */        static void Main(string[] args)        {            Console.WriteLine("定義{0}個(gè)人煮飯3次", _particpants);            _CookTasks = new Task[_particpants];            _barrier = new Barrier(_particpants, (barrier) =>            {                Console.WriteLine("當(dāng)前階段:{0}", barrier.CurrentPhaseNumber);            });            Stopwatch swTask1 = new Stopwatch();            swTask1.Start();            /*定義N個(gè)人*/            for (int cook_person = 0; cook_person < _particpants; cook_person++)            {                _CookTasks[cook_person] = Task.Factory.StartNew((num) =>                {                    int index = Convert.ToInt32(num);                    /*每個(gè)人煮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 提供一組任務(wù)完成后 延續(xù)方法*/            var finalTask = Task.Factory.ContinueWhenAll(_CookTasks, (tasks) =>            {                /*等待任務(wù)完成*/                Task.WaitAll(_CookTasks);                swTask1.Stop();                Console.WriteLine("采用并發(fā) {1}個(gè)人煮3次飯耗時(shí):{0}", swTask1.ElapsedMilliseconds, _particpants);                /*釋放資源*/                _barrier.Dispose();            });            Thread.Sleep(4000);            Stopwatch swTask = new Stopwatch();            swTask.Start();            /*定義N個(gè)人*/            for (int cook_person = 0; cook_person < _particpants; cook_person++)            {                /*每個(gè)人煮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("不采用并發(fā) {1}個(gè)人煮3次飯耗時(shí):{0}", swTask.ElapsedMilliseconds, _particpants);            Thread.Sleep(2000);            Console.ReadLine();        }        /*1.打水*/        private static void CookStepTask1(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 打水... 耗時(shí)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}次 淘米... 耗時(shí)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}次 放入鍋中... 耗時(shí)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}次 蓋上鍋蓋... 耗時(shí)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}次  生火煮飯... 耗時(shí)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}次 打水... 耗時(shí)2分鐘", pesron_index, index);            Thread.Sleep(200);        }        /*2.淘米*/        private static void CookStep2(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 淘米... 耗時(shí)3分鐘", pesron_index, index);            Thread.Sleep(300);        }        /*3.放入鍋中*/        private static void CookStep3(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 放入鍋中... 耗時(shí)1分鐘", pesron_index, index);            Thread.Sleep(100);        }        /*4.蓋上鍋蓋*/        private static void CookStep4(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次 蓋上鍋蓋... 耗時(shí)1分鐘", pesron_index, index);            Thread.Sleep(100);        }        /*5.生火煮飯*/        private static void CookStep5(int pesron_index, int index)        {            Console.WriteLine("{0} 第{1}次  生火煮飯... 耗時(shí)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

如代碼所示,在串行代碼中,雖然任務(wù)是有序進(jìn)行,但是等待的時(shí)間很長(zhǎng),因?yàn)橹皇窃谝粋€(gè)處理器下進(jìn)行處理,如下圖所示:

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

ContinueWhenAll 提供一組任務(wù)完成后的延續(xù)方法

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 日本娇小videos高潮 | 欧美激情性色生活片在线观看 | 97久久曰曰久久久 | 成人福利在线播放 | 成年免费看 | 午夜视频在线免费观看 | 暴力肉体进入hdxxxx古装 | 在线免费小视频 | 神马福利电影 | 亚洲婷婷日日综合婷婷噜噜噜 | 污片视频网站 | 在线看一区二区三区 | 中国免费一级毛片 | 国产精品久久久久影院老司 | 91精品国产综合久久久动漫日韩 | 爱视频福利 | 亚洲情av | 精品一区二区三区免费毛片 | 久久国产成人精品国产成人亚洲 | 欧洲精品色 | 久久99国产伦子精品免费 | 色综合欧美 | 欧美日韩免费一区二区三区 | 日韩精品中文字幕在线播放 | sese在线视频 | cosplay裸体福利写真 | 孕妇体内谢精满日本电影 | 最新av在线播放 | 免费一级毛片网站 | 一级毛片免费高清视频 | 96视频在线免费观看 | 沉沦的校花奴性郑依婷c到失禁 | 亚洲最大久久 | 欧美va亚洲 | 日本高清无遮挡 | 操皮视频 | 激情久久免费视频 | 得得啪在线视频 | 综合网日日天干夜夜久久 | 久久精品探花 | 午夜视频在线观看91 |