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

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

多線程中的鎖系統(tǒng)(三)-WaitHandle、AutoResetEvent、ManualResetEvent

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

多線程中的鎖系統(tǒng)(三)-WaitHandle、AutoResetEvent、ManualResetEvent

2015-01-10 08:45 by 蘑菇先生, ... 閱讀, ... 評(píng)論, 收藏, 編輯

本章主要介紹下基于內(nèi)核模式構(gòu)造的線程同步方式,事件,信號(hào)量。

閱讀目錄:

  1. 理論
  2. WaitHandle
  3. AutoResetEvent
  4. ManualResetEvent
  5. 總結(jié)

理論

Windows的線程同步方式可分為2種,用戶模式構(gòu)造和內(nèi)核模式構(gòu)造。

內(nèi)核模式構(gòu)造:是由Windows系統(tǒng)本身使用,內(nèi)核對(duì)象進(jìn)行調(diào)度協(xié)助的。內(nèi)核對(duì)象是系統(tǒng)地址空間中的一個(gè)內(nèi)存塊,由系統(tǒng)創(chuàng)建維護(hù)。

  內(nèi)核對(duì)象為內(nèi)核所擁有,而不為進(jìn)程所擁有,所以不同進(jìn)程可以訪問(wèn)同一個(gè)內(nèi)核對(duì)象,如進(jìn)程,線程,作業(yè),事件,文件,信號(hào)量,互斥量等都是內(nèi)核對(duì)象。

  而信號(hào)量,互斥體,事件是Windows專門(mén)用來(lái)幫助我們進(jìn)行線程同步的內(nèi)核對(duì)象。

  對(duì)于線程同步操作來(lái)說(shuō),內(nèi)核對(duì)象只有2個(gè)狀態(tài), 觸發(fā)(終止,true)、未觸發(fā)(非終止,false)。 未觸發(fā)不可調(diào)度,觸發(fā)可調(diào)度。

用戶模式構(gòu)造:是由特殊CPU指令來(lái)協(xié)調(diào)線程,上節(jié)講的volatile實(shí)現(xiàn)就是一種,Interlocked也是。 也可稱為非阻塞線程同步。

WaitHandle

在windows編程中,通過(guò)API創(chuàng)建一個(gè)內(nèi)核對(duì)象后會(huì)返回一個(gè)句柄,句柄則是每個(gè)進(jìn)程句柄表的索引,而后可以拿到內(nèi)核對(duì)象的指針、掩碼、標(biāo)示等。

而WaitHandle抽象基類類作用是包裝了一個(gè)windows內(nèi)核對(duì)象的句柄。我們來(lái)看下其中一個(gè)WaitOne的函數(shù)源碼(略精簡(jiǎn))。

        public virtual bool WaitOne(TimeSpan timeout)        {            return WaitOne(timeout, false);         }        [System.Security.SecuritySafeCritical]  // auto-generated        [Sup

WaitAll 和WaitAny 調(diào)用win32中,waitformultipleobjectsEx函數(shù)。

SignalAndWaitOne 調(diào)用win32中,signalandwait函數(shù)。

調(diào)用api帶ex都是設(shè)置超時(shí)的。 如果我們?cè)赾#中不傳,默認(rèn)是-1 表示無(wú)限期等待。

其中SafeWaitHandle字段,包含了一個(gè)win32內(nèi)核對(duì)象句柄。

理解了WaitHandle其他都好辦了,我們來(lái)看下它的派生類型。

WaitHandle   |——EventWaitHandle 事件構(gòu)造。     |——AutoResetEvent     |——ManualResetEvent   |——Semaphore 信號(hào)量構(gòu)造。   |——Mutex 互斥體構(gòu)造。

其中Semaphore和mutex第一篇已經(jīng)介紹過(guò)了,下面來(lái)看看其他的。

AutoResetEvent

使用示例如下,有簡(jiǎn)單注釋。 關(guān)于描述,盡量貼近系統(tǒng)自身術(shù)語(yǔ)。

  static void Main(string[] args)        {            //AutoResetEvent example            //AutoResetEvent 通知正在等待的線程已發(fā)生的事件。            AutoResetEvent waitHandler = new AutoResetEvent(false);//false 即非終止,未觸發(fā)。            new Thread(() =>            {                waitHandler.WaitOne();  //阻塞當(dāng)前線程,等待底層內(nèi)核對(duì)象收到信號(hào)。                Console.WriteLine("接收到信號(hào),開(kāi)始處理。");            }).Start();            new Thread(() =>            {                Thread.Sleep(2000);                Console.WriteLine("發(fā)信號(hào)");                waitHandler.Set();    //向內(nèi)核對(duì)象發(fā)送信號(hào)。設(shè)置事件對(duì)象為非終止?fàn)顟B(tài)、false,解除阻塞。              }).Start();            //waitHandler.Close(); //釋放句柄資源。            //waitHandler.Reset();  //手動(dòng)設(shè)置事件為非終止?fàn)顟B(tài)、false,線程阻止。            Console.ReadLine();        }

WaitOne 阻塞線程,非自旋。

Set() 發(fā)出一個(gè)信號(hào)后,設(shè)置事件狀態(tài)為false。 這本應(yīng)該是2步的操作,AutoResetEvent.set()函數(shù),給2步一起自動(dòng)做了,很方便。

ManualResetEvent

這個(gè)和上面基本一樣,從字面來(lái)說(shuō)需要手動(dòng)重置狀態(tài),我們來(lái)看例子。

            ManualResetEvent manualWaitHandler = new ManualResetEvent(false);//false 即非終止,未觸發(fā)。            new Thread(() =>            {                manualWaitHandler.WaitOne();  //阻塞當(dāng)前線程對(duì)象,等待信號(hào)。                Console.WriteLine("接收到信號(hào),開(kāi)始處理。");                manualWaitHandler.Reset();  //手動(dòng) 設(shè)置事件對(duì)象狀態(tài)為非終止?fàn)顟B(tài),false。                manualWaitHandler.WaitOne();  //這里直接阻塞等待無(wú)效,因?yàn)槭录?duì)象還是true,必須手動(dòng)調(diào)reset。                Console.WriteLine("第二次接收到信號(hào),開(kāi)始處理。");            }).Start();            new Thread(() =>            {                Thread.Sleep(2000);                Console.WriteLine("發(fā)信號(hào)");                manualWaitHandler.Set();    //向事件對(duì)象發(fā)送ok信號(hào)。。                Thread.Sleep(2000);                Console.WriteLine("第二次發(fā)信號(hào)");                manualWaitHandler.Set();            }).Start();            Console.ReadLine();

這2者區(qū)別很小,其實(shí)是系統(tǒng)Api的區(qū)分,不是net類庫(kù)實(shí)現(xiàn)的。

在Win32Native類中,我可以看到KERNEL32 api 有這么個(gè)參數(shù)isManualReset。

 [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]        [ResourceExposure(ResourceScope.Machine)] // Machine or none based on the value of "name"        internal static extern SafeWaitHandle CreateEvent(SECURITY_ATTRIBUTES lpSecurityAttributes, bool isManualReset, bool initialState, String name);

總結(jié)

基于內(nèi)核模式構(gòu)造的同步步驟是: 托管代碼->用戶模式代碼->內(nèi)核模式代碼。

用戶模式構(gòu)造, 是利用CPU特殊指令,進(jìn)行原子操作。

用戶模式代碼,如圖。 是指 托管代碼調(diào)用 win32代碼 這一層, 之后在調(diào)內(nèi)核模式代碼。

參考CLR via c#及Windows核心編程第五版。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 霍林郭勒市| 广平县| 溧阳市| 庄河市| 信阳市| 东光县| 岗巴县| 乌拉特中旗| 阜阳市| 屏东县| 八宿县| 深水埗区| 黎城县| 桂林市| 永安市| 佛冈县| 航空| 纳雍县| 咸丰县| 清河县| 本溪市| 通辽市| 泰和县| 德州市| 祥云县| 蒙自县| 拜城县| 大邑县| 崇左市| 漳浦县| 扬中市| 宜兰市| 天水市| 苏尼特左旗| 广昌县| 马尔康县| 拜泉县| 秭归县| 留坝县| 邵东县| 龙海市|