小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

多線程中的lock,Monitor.Wait和Monitor.Pulse

 orion360doc 2011-12-12

        有CSDN的朋友問一個(gè)問題,“Lock關(guān)鍵字不是有獲取鎖、釋放鎖的功能嗎?...為什么還需要執(zhí)行Pulse?”
        也有朋友有些疑點(diǎn),“用lock就不要用monitor了”,“Monitor.Wait完全沒必要”,“為什么Pulse和Wait方法必須從同步的代碼塊內(nèi)調(diào)用?”

        這些疑問很自然。在大部分情況下,lock確實(shí)能基本達(dá)到我們要求資源同步的目的,加上配合其他同步工具,比如事件(AutoResetEvent)等的應(yīng)用,日常工作中確實(shí)沒有太多機(jī)會(huì)需要用到Monitor.Wait和Pulse。不過,雖然較少機(jī)會(huì)用到,事實(shí)上Wait和Pulse跟lock完全不是一回事。他們提供了更細(xì)膩的同步功能,能達(dá)到lock作不來的功能。

        為更好的回答和解釋這些疑問,該帖將首先介紹Wait和Pulse的用途,通過一個(gè)簡單例子逐條分析同步的過程;然后提供一個(gè)用輕量級的lock,Wait和Pulse來實(shí)現(xiàn)一個(gè)事件通知的實(shí)例;最后談?wù)凞otNet4對lock編譯展開的一點(diǎn)有趣變化。

        朋友們的原貼可以在隨后的注釋中找到鏈接。
        • gomoku用戶頭像
        • gomoku
        • (IDynamicObject)
        • 等 級:
        #1樓 得分:0回復(fù)于:2011-12-09 18:24:56
        讓我們首先看看MSDN對Monitor.Wait的解釋(鏈接見注釋):
        釋放對象上的鎖并阻止當(dāng)前線程,直到它重新獲取該鎖。...

        該解釋的確很粗糙,很難理解。讓我們來看看它下面的備注:
        同步的對象包含若干引用,其中包括對當(dāng)前擁有鎖的線程的引用、對就緒隊(duì)列的引用和對等待隊(duì)列的引用。

        這個(gè)多少還給了點(diǎn)東西,現(xiàn)在我們腦海中想像這么一幅圖畫:
        Assembly code
        |- 擁有鎖的線程 lockObj->|- 就緒隊(duì)列(ready queue) |- 等待隊(duì)列(wait queue)
        當(dāng)一個(gè)線程嘗試著lock一個(gè)同步對象的時(shí)候,該線程就在就緒隊(duì)列中排隊(duì)。一旦沒人擁有該同步對象,就緒隊(duì)列中的線程就可以占有該同步對象。這也是我們平時(shí)最經(jīng)常用的lock方法。
        為了其他的同步目的,占有同步對象的線程也可以暫時(shí)放棄同步對象,并把自己流放到等待隊(duì)列中去。這就是Monitor.Wait。由于該線程放棄了同步對象,其他在就緒隊(duì)列的排隊(duì)者就可以進(jìn)而擁有同步對象。
        比起就緒隊(duì)列來說,在等待隊(duì)列中排隊(duì)的線程更像是二等公民:他們不能自動(dòng)得到同步對象,甚至不能自動(dòng)升艙到就緒隊(duì)列。而Monitor.Pulse的作用就是開一次門,使得一個(gè)正在等待隊(duì)列中的線程升艙到就緒隊(duì)列;相應(yīng)的Monitor.PulseAll則打開門放所有等待隊(duì)列中的線程到就緒隊(duì)列。

        比如下面的程序:
        C# code
        class Program { static void Main(string[] args) { new Thread(A).Start(); new Thread(B).Start(); new Thread(C).Start(); Console.ReadLine(); } static object lockObj = new object(); static void A() { lock (lockObj) //進(jìn)入就緒隊(duì)列 { Thread.Sleep(1000); Monitor.Pulse(lockObj); Monitor.Wait(lockObj); //自我流放到等待隊(duì)列 } Console.WriteLine("A exit..."); } static void B() { Thread.Sleep(500); lock (lockObj) //進(jìn)入就緒隊(duì)列 { Monitor.Pulse(lockObj); } Console.WriteLine("B exit..."); } static void C() { Thread.Sleep(800); lock (lockObj) //進(jìn)入就緒隊(duì)列 { } Console.WriteLine("C exit..."); } }


        從時(shí)間線上來分析:
        Assembly code
        T 線程A 0 lock( lockObj ) 1 { 2 //... 線程B 線程C 3 //... lock( lockObj ) lock( lockObj ) 4 //... { { 5 //... //... 6 //... //... 7 Monitor.Pulse //... 8 Monitor.Wait //... 9 //... Monitor.Pulse 10 //... } } 11 } 時(shí)間點(diǎn)0,假設(shè)線程A先得到了同步對象,它就登記到同步對象lockObj的“擁有者引用”中。 時(shí)間點(diǎn)3,線程B和C要求擁有同步對象,他們將在“就緒隊(duì)列”排隊(duì): |--(擁有鎖的線程) A | 3 lockObj--|--(就緒隊(duì)列) B,C | |--(等待隊(duì)列) 時(shí)間點(diǎn)7,線程A用Pulse發(fā)出信號,允許第一個(gè)正在"等待隊(duì)列"中的線程進(jìn)入到”就緒隊(duì)列“。但由于就緒隊(duì)列是空的,什么事也沒有發(fā)生。 時(shí)間點(diǎn)8,線程A用Wait放棄同步對象,并把自己放入"等待隊(duì)列"。B,C已經(jīng)在就緒隊(duì)列中,因此其中的一個(gè)得以獲得同步對象(假定是B)。B成了同步 對象的擁有者。C現(xiàn)在還是候補(bǔ)委員,可以自動(dòng)獲得空缺。而A則被關(guān)在門外,不能自動(dòng)獲得空缺。 |--(擁有鎖的線程) B | 8 lockObj--|--(就緒隊(duì)列) C | |--(等待隊(duì)列) A 時(shí)間點(diǎn)9,線程B用Pulse發(fā)出信號開門,第一個(gè)被關(guān)在門外的A被允許放入到就緒隊(duì)列,現(xiàn)在C和A都成了候補(bǔ)委員,一旦同步對象空閑,都有機(jī)會(huì)得它。 |--(擁有鎖的線程) B | 9 lockObj--|--(就緒隊(duì)列) C,A | |--(等待隊(duì)列) 時(shí)間點(diǎn)10,線程B退出Lock區(qū)塊,同步對象閑置,就緒隊(duì)列隊(duì)列中的C或A就可以轉(zhuǎn)正為擁有者(假設(shè)C得到了同步對象)。 |--(擁有鎖的線程) C | 10 lockObj--|--(就緒隊(duì)列) A | |--(等待隊(duì)列) 隨后C也退出Lock區(qū)塊,同步對象閑置,A就重新得到了同步對象,并從Monitor.Wait中返回... 最終的執(zhí)行結(jié)果就是: B exit... C exit... A exit...
        • gomoku用戶頭像
        • gomoku
        • (IDynamicObject)
        • 等 級:
        #3樓 得分:0回復(fù)于:2011-12-09 18:39:35
        由于Monitor.Wait的暫時(shí)放棄和Monitor.Pulse的開門機(jī)制,我們可以用Monitor來實(shí)現(xiàn)更豐富的同步機(jī)制,比如一個(gè)事件機(jī)(ManualResetEvent):
        C# code
        class MyManualEvent { private object lockObj = new object(); private bool hasSet = false; public void Set() { lock (lockObj) { hasSet = true; Monitor.PulseAll(lockObj); } } public void WaitOne() { lock (lockObj) { while (!hasSet) { Monitor.Wait(lockObj); } } } } class Program { static MyManualEvent myManualEvent = new MyManualEvent(); static void Main(string[] args) { ThreadPool.QueueUserWorkItem(WorkerThread, "A"); ThreadPool.QueueUserWorkItem(WorkerThread, "B"); Console.WriteLine("Press enter to signal the green light"); Console.ReadLine(); myManualEvent.Set(); ThreadPool.QueueUserWorkItem(WorkerThread, "C"); Console.ReadLine(); } static void WorkerThread(object state) { myManualEvent.WaitOne(); Console.WriteLine("Thread {0} got the green light...", state); } }

        我們看到了該玩具M(jìn)yManualEvent實(shí)現(xiàn)了類庫中的ManulaResetEvent的功能,但卻更加的輕便 - 類庫的ManulaResetEvent使用了操作系統(tǒng)內(nèi)核事件機(jī)制,負(fù)擔(dān)比較大(不算競態(tài)時(shí)間,ManulaResetEvent是微秒級,而lock是幾十納秒級)。

        例子的WaitOne中先在lock的保護(hù)下判斷是否信號綠燈,如果不是則進(jìn)入等待。因此可以有多個(gè)線程(比如例子中的AB)在等待隊(duì)列中排隊(duì)。
        當(dāng)調(diào)用Set的時(shí)候,在lock的保護(hù)下信號轉(zhuǎn)綠,并使用PulseAll開門放狗,將所有排在等待隊(duì)列中的線程放入就緒隊(duì)列,A或B(比如A)于是可以重新獲得同步對象,從Monitor.Wait退出,并隨即退出lock區(qū)塊,WaitOne返回。隨后B或A(比如B)重復(fù)相同故事,并從WaitOne返回。
        線程C在myManualEvent.Set()后才執(zhí)行,它在WaitOne中確信信號燈早已轉(zhuǎn)綠,于是可以立刻返回并得以執(zhí)行隨后的命令。

        該玩具M(jìn)yManualEvent可以用在需要等待初始化的場合,比如多個(gè)工作線程都必須等到初始化完成后,接到OK信號后才能開工。該玩具M(jìn)yManualEvent比起ManulaResetEvent有很多局限,比如不能跨進(jìn)程使用,但它演示了通過基本的Monitor命令組合,達(dá)到事件機(jī)的作用。

        現(xiàn)在是回答朋友們的疑問的時(shí)候了:
        Q: Lock關(guān)鍵字不是有獲取鎖、釋放鎖的功能... 為什么還需要執(zhí)行Pulse?
        A: 因?yàn)閃ait和Pulse另有用途。

        Q: 用lock 就不要用monitor了(?)
        A: lock只是Monitor.Enter和Monitor.Exit,用Monitor的方法,不僅能用Wait,還可以用帶超時(shí)的Monitor.Enter重載。

        Q: Monitor.Wait完全沒必要 (?)
        A: Wait和Pulse另有用途。

        Q: 什么Pulse和Wait方法必須從同步的代碼塊內(nèi)調(diào)用?
        A: 因?yàn)閃ait的本意就是“[暫時(shí)]釋放對象上的鎖并阻止當(dāng)前線程,直到它重新獲取該鎖”,沒有獲得就談不到釋放。


        我們知道lock實(shí)際上一個(gè)語法糖糖,C#編譯器實(shí)際上把他展開為Monitor.Enter和Monitor.Exit,即:
        C# code
        lock(lockObj) { //... } ////相當(dāng)于(.Net4以前): Monitor.Enter(lockObj); try { //... } finally { Monitor.Exit(lockObj); }

        但是,這種實(shí)現(xiàn)邏輯至少理論上有一個(gè)錯(cuò)誤:當(dāng)Monitor.Enter(lockObj);剛剛完成,還沒有進(jìn)入try區(qū)的時(shí)候,有可能從其他線程發(fā)出了Thread.Abort等命令,使得該線程沒有機(jī)會(huì)進(jìn)入try...finally。也就是說lockObj沒有辦法得到釋放,有可能造成程序死鎖。這也是Thread.Abort一般被認(rèn)為是邪惡的原因之一。

        DotNet4開始,增加了Monitor.Enter(object,ref bool)重載。而C#編譯器會(huì)把lock展開為更安全的Monitor.Enter(object,ref bool)和Monitor.Exit:
        C# code
        lock(lockObj) { //... } ////相當(dāng)于(DotNet 4): bool lockTaken = false; try { Monitor.Enter(lockObj,ref lockTaken); // } finally { if (lockTaken) Monitor.Exit(lockObj); }

        現(xiàn)在Monitor.TryEnter在try的保護(hù)下,“加鎖”成功意味著“放鎖”將得到finally的保護(hù)。


        注釋和引用:
        Monitor.Wait 方法
        http://msdn.microsoft.com/zh-cn/library/79fkfcw1.aspx

        Monitor.TryEnter 方法
        http://msdn.microsoft.com/zh-cn/library/dd289679.aspx

        請問,多線程Monitor類
        http://topic.csdn.net/u/20111206/15/744c70de-49dc-4694-a09e-180438d7f8f0.html

        請問,這個(gè)關(guān)于多線程的代碼不懂
        http://topic.csdn.net/u/20111208/23/64671dd4-7fdc-4d76-b3b9-1fd18087e6e0.html
        #8樓 得分:0回復(fù)于:2011-12-09 19:19:44
        恩 講的很清楚  
        學(xué)習(xí)了.

        以前就用Monitor.Wait 實(shí)現(xiàn)對于大量線程的阻塞 達(dá)到暫停效果
        #9樓 得分:0回復(fù)于:2011-12-09 19:27:59


        今天回答線程問題的時(shí)候,讓我有寫總結(jié)的沖動(dòng),我實(shí)在是很懶。

        gomoku 寫了這篇文章真的是太好了。

        “朋友們的疑問”那天看到的時(shí)候,真的有些無奈,那些回答會(huì)對提問者有誤導(dǎo)。

        還請樓下的朋友們不要無意義回復(fù)。想收藏可以點(diǎn)文章標(biāo)題右側(cè)的收藏。

        同時(shí)也請gomoku把帖子挪到asp.net版,好讓我有編輯的權(quán)限。
        #11樓 得分:0回復(fù)于:2011-12-09 20:08:22
        C# code
        static object lockObj = new object(); static void A() { lock (lockObj) //進(jìn)入就緒隊(duì)列 { //因?yàn)锳所在的線程Priority高,所以會(huì)先進(jìn)來 Console.WriteLine("Into A lock block"); Thread.Sleep(1000); //這里調(diào)用了Monitor.Pulse(lockObj),會(huì)通知lockObj的等待隊(duì)列 //但現(xiàn)在lockObj的等待隊(duì)列沒有線程在等待,所以通知不被處理 Monitor.Pulse(lockObj); //自我流放到等待隊(duì)列 Monitor.Wait(lockObj);//同時(shí)此線程在此停止 //線程此時(shí)的狀態(tài)是WaitSleepJoin //雖然在Monitor.Wait之前有Monitor.Pulse通知等待隊(duì)列,但是過期無效。 //無論之前有多少個(gè)Monitor.Pulse //本線程在等待隊(duì)列后接受到Monitor.Pulse的通知時(shí),線程回到就緒隊(duì)列 //從就緒隊(duì)列中出來的時(shí)候,線程在此恢復(fù) } Console.WriteLine("A exit..."); } static void B() { lock (lockObj) //進(jìn)入就緒隊(duì)列 { //B和C都在就緒隊(duì)列,因?yàn)锽所在的線程Priority比C高,所以會(huì)先進(jìn)來 Console.WriteLine("Into B lock block"); //這里調(diào)用了Monitor.Pulse(lockObj),會(huì)通知lockObj的等待隊(duì)列 //于此同時(shí),A 已經(jīng)在等待隊(duì)列了 Monitor.Pulse(lockObj); Console.WriteLine("B Call Pulse"); } Console.WriteLine("B lock block exit..."); Thread.Sleep(1); Console.WriteLine("B exit..."); } static void C() { //如果CPU是低負(fù)載理想的情況,此時(shí)的就緒隊(duì)列中會(huì)有兩個(gè)線程 //除了C還有接收到信號的A,C排在前面理想情況會(huì)先進(jìn)來 但不是絕對,有時(shí)會(huì)是A lock (lockObj) //進(jìn)入就緒隊(duì)列 { Console.WriteLine("Into C lock block"); } Console.WriteLine("C exit..."); } static void Main(string[] args) { //設(shè)置Priority,確保按代碼順序執(zhí)行 Thread a = new Thread(A); a.Priority = ThreadPriority.Highest; a.Start(); Thread b = new Thread(B); b.Priority = ThreadPriority.Normal; b.Start(); Thread c = new Thread(C); c.Priority = ThreadPriority.Lowest; c.Start(); Console.ReadLine(); }


        最后輸出的三句話 
        C exit...
        B exit...
        A exit...

        順序不是固定的,而是要結(jié)合CPU等系統(tǒng)資源的調(diào)配
        #12樓 得分:0回復(fù)于:2011-12-09 20:37:52
        引用 11 樓 sandy945 的回復(fù):

        C# code

        static object lockObj = new object();

        static void A()
        {

        lock (lockObj) //進(jìn)入就緒隊(duì)列
        {
        //因?yàn)锳所在的線程Priority高,所以會(huì)先進(jìn)來
        Console.WriteLine("Into A lock block");
        ……

        lz只是假設(shè)A先得到lock
        非常棒的技術(shù)貼,mark
        • hyblusea用戶頭像
        • hyblusea
        • (C-Sharp[機(jī)器貓])
        • 等 級:
        #18樓 得分:0回復(fù)于:2011-12-09 23:39:40
        占個(gè)位置,以后仔細(xì)學(xué)習(xí)
        • koyo22用戶頭像
        • koyo22
        • (koyo22)
        • 等 級:
        #19樓 得分:0回復(fù)于:2011-12-10 01:14:05
        非常好,
        #20樓 得分:0回復(fù)于:2011-12-10 02:03:39
        樓主恩細(xì)心啊,學(xué)習(xí)哦
        • mrlen用戶頭像
        • mrlen
        • (林別卓)
        • 等 級:
        #22樓 得分:0回復(fù)于:2011-12-10 08:10:38
        神貼。收藏看。還沒用這么復(fù)雜的
        • sdfkfkd用戶頭像
        • sdfkfkd
        • (特別(男))
        • 等 級:
        #32樓 得分:0回復(fù)于:2011-12-10 12:32:13
        引用 12 樓 yuxuanji 的回復(fù):

        引用 11 樓 sandy945 的回復(fù):

        C# code

        static object lockObj = new object();

        static void A()
        {

        lock (lockObj) //進(jìn)入就緒隊(duì)列
        {
        //因?yàn)锳所在的線程Priority高,所以會(huì)先進(jìn)來
        Console.WriteLine("Into A lock……

        +1
        #33樓 得分:0回復(fù)于:2011-12-10 12:48:09
        學(xué)習(xí)了,以前沒有了解的這么細(xì)
        #35樓 得分:0回復(fù)于:2011-12-10 13:31:14
        寫的挺好
        不過你把順序搞反了吧,monitor是win32的概念,而lock是c#的語法
        應(yīng)該是先有monitor再有l(wèi)ock
        #36樓 得分:0回復(fù)于:2011-12-10 13:41:33
        介紹的到位 
          頂!
        #37樓 得分:0回復(fù)于:2011-12-10 14:09:31
        恩 講的很清楚  
        學(xué)習(xí)了
        • xienb用戶頭像
        • xienb
        • (xienb)
        • 等 級:
        #38樓 得分:0回復(fù)于:2011-12-10 16:58:00
        恩, 來學(xué)習(xí)下 ,希望有分 謝謝
        #39樓 得分:0回復(fù)于:2011-12-10 17:30:04
        收下,慢慢分析一下 ~~~
        • zanfeng用戶頭像
        • zanfeng
        • (qq:1060151476)
        • 等 級:
        #40樓 得分:0回復(fù)于:2011-12-10 17:44:21
        技術(shù)貼值得推薦。頂頂。
        #41樓 得分:0回復(fù)于:2011-12-10 18:16:39
        好貼,支持
        #42樓 得分:0回復(fù)于:2011-12-10 18:35:16
        講解的好
        #44樓 得分:0回復(fù)于:2011-12-10 19:40:38
        經(jīng)測試,AutoResetEvent的效率和Monitor.Wait幾乎一樣,有心人可以測試對比一下。
        Monitor.Enter等待時(shí)間如果很長,也是會(huì)進(jìn)入內(nèi)核態(tài)的,它對應(yīng)的是win32的CRITICAL_SECTION結(jié)構(gòu)。但是Monitor.Wait對應(yīng)哪個(gè)win32 api我沒找到,或者它是.net新創(chuàng)了一個(gè)以前win32所沒有的東西,我懷疑Monitor.Wait也會(huì)進(jìn)入內(nèi)核態(tài),在這點(diǎn)上和WaitHandle實(shí)質(zhì)相同。
        • lmc158用戶頭像
        • lmc158
        • (成功)
        • 等 級:
        #45樓 得分:0回復(fù)于:2011-12-10 20:56:29
        就緒隊(duì)列。而Monitor.Pulse的作用就是開一次門,使得一個(gè)正在等待隊(duì)列中的線程升艙到就緒隊(duì)列;相應(yīng)的Monitor.PulseAll則打開門放所有等待隊(duì)列中的線程到就緒隊(duì)列。
        #46樓 得分:0回復(fù)于:2011-12-10 23:59:32
        收下了
        • gomoku用戶頭像
        • gomoku
        • (IDynamicObject)
        • 等 級:
        #50樓 得分:0回復(fù)于:2011-12-11 09:58:22
        如可行,也煩請斑竹在原文(3樓)中改正:
        錯(cuò)誤更正:

        1、是有關(guān)開銷:
        (不算競態(tài)時(shí)間,ManulaResetEvent是秒級,而lock是幾十秒級)。注:非競態(tài)下的比較不能算公平;而多線程下卻很難進(jìn)行比較,特別是摻雜了系統(tǒng)調(diào)度的因素和線程切換的開銷。

        2、是有關(guān)lock的編譯展開:
        DotNet4開始,增加了Monitor.Enter(object,ref bool)重載。而C#編譯器會(huì)把lock展開為更安全的Monitor.Enter(object,ref bool)和Monitor.Exit:
        C# code
        lock(lockObj) { //... } ////相當(dāng)于(DotNet 4): bool lockTaken = false; try { Monitor.Enter(lockObj,ref lockTaken); // } finally { if (lockTaken) Monitor.Exit(lockObj); }
        • flyerwing用戶頭像
        • flyerwing
        • (80年代的內(nèi)褲)
        • 等 級:
        #51樓 得分:0回復(fù)于:2011-12-11 10:44:17
        看看大蝦的研究成果。
        #54樓 得分:0回復(fù)于:2011-12-11 12:13:46
        我查了半天Monitor.Wait的源碼,到了ObjWait(bool exitContext, int millisecondsTimeout, object obj)這里就終止了,無法看到他的具體實(shí)現(xiàn)。不過我還是查到了一篇文章,這篇文章本身不用看,看下面的評論很有意思。
        http://www.cnblogs.com/cn_wpf/archive/2007/07/20/825059.html
        其中一條評論:
        “internal call的實(shí)現(xiàn)在CLR的虛擬機(jī)實(shí)現(xiàn)(sscli20\clr\src\vm)里, 但不僅僅是這個(gè)文件夾, clr\src中除了bcl文件夾都不是托管代碼
        Monitor.Wait的實(shí)現(xiàn)->Monitor.ObjWait是個(gè)internal call方法, 可以在ecall.h中搜索到FCFuncElement("ObjWait", ObjectNative::WaitTimeout), 所以其實(shí)它其實(shí)是調(diào)用了ObjectNative::WaitTimeout, 找到這個(gè)函數(shù)實(shí)現(xiàn)往下挖X層之后你就能在synch.cpp里找到的CLREventWaitHelper函數(shù)中找到Win32API的調(diào)用:WaitForSingleObjectEx”

        AutoResetEvent實(shí)際調(diào)用的也是WaitForSingleObject,那么想象一下,如果Monitor.Wait和AutoResetEvent真的有所區(qū)別的話,也許Monitor.Wait會(huì)在進(jìn)入內(nèi)核態(tài)之前自旋一小段時(shí)間,如果線程操作處理的足夠快,也許不會(huì)進(jìn)入內(nèi)核態(tài),但這只是想象,希望能得到證實(shí)。注意這里只說Monitor.Wait,因?yàn)镸onitor.Enter可以確認(rèn)會(huì)先自旋。
        #55樓 得分:0回復(fù)于:2011-12-11 18:36:58
        俺是來看多線程同步、互斥的,沒想到是ASP的技術(shù)。
        不過無論是C++,Java,還是ASP,多線程的基礎(chǔ)設(shè)施應(yīng)該在抽象層上差不多
        #60樓 得分:0回復(fù)于:2011-12-12 02:52:22
        技術(shù)分享是希望能夠幫助更多需要幫助的人,如果大家有與本帖內(nèi)容相關(guān)的疑問可以提出來,LZ有時(shí)間肯定會(huì)做出解答的,大家也可以一起集思廣益。如果有人能分享心得體會(huì)那更是求之不得。
        所以還請大家不要無意義回復(fù),試想你對此類問題有疑問,卻翻了好幾頁沒找到關(guān)鍵的部分,滿篇的灌水什么心情,如果你覺得本文對你幫助很大,想查閱又怕記憶繁瑣可以點(diǎn)擊標(biāo)題右側(cè)的收藏。
        本回復(fù)之前的無意義回復(fù),都會(huì)通知回復(fù)人之后刪除,由于精力有限本回復(fù)之后的無意義回復(fù)刪除恕不另行通知。
        #61樓 得分:0回復(fù)于:2011-12-12 04:31:10
        不好意思,我說一句廢話,阿非刪除不用通知我了。

        我就想說,這個(gè)貼是昨天吃早餐的時(shí)候方興和我提到的。所以我一定要瞻仰下。
        • jhdxhj用戶頭像
        • jhdxhj
        • (jhdxhj)
        • 等 級:
        #63樓 得分:0回復(fù)于:2011-12-12 09:52:23
        非常好,恩,原來是這樣啊 
        • Mpt_hi用戶頭像
        • Mpt_hi
        • (月光下的土豆)
        • 等 級:
        #64樓 得分:0回復(fù)于:2011-12-12 09:58:48
        收藏備用
        • ohkuy用戶頭像
        • ohkuy
        • (Null)
        • 等 級:
        #67樓 得分:0回復(fù)于:2011-12-12 12:11:56
        神帖啊,
        以前沒注意這么細(xì)節(jié)化的東西,
        講得很好,很細(xì),
        受教了
        希望先推薦,再置頂,
        要不是我眼神好,差點(diǎn)忽略了
        #68樓 得分:0回復(fù)于:2011-12-12 13:26:02
        非常好的帖子,溫故一下,感謝樓主分享
        #69樓 得分:0回復(fù)于:2011-12-12 13:47:18
        Windows Vista新增了條件變量,這樣在使用CRITICAL_SECTION關(guān)鍵代碼段期間,可以調(diào)用SleepConditionVariableCS來放棄鎖的所有權(quán)并阻止線程,直到被另一線程調(diào)用WakeConditionVariable喚醒,重新嘗試進(jìn)入臨界區(qū)。這個(gè)和Monitor的所有方法都可以一一對應(yīng)了,也意味著Monitor.Wait在Vista之前與之后的操作系統(tǒng)上應(yīng)該有不同的表現(xiàn)。
        “條件變量在某些情況中也可能更高效。SleepConditionVariableCS 和 SleepConditionVariableSRW API 會(huì)盡可能候試圖避免進(jìn)入內(nèi)核模式的行程。但不使用條件變量的示例在調(diào)用 WaitForSingleObject 時(shí),總是會(huì)發(fā)生至少一次內(nèi)核模式往返。”
        http://msdn.microsoft.com/zh-cn/magazine/cc163405.aspx
        • youbl用戶頭像
        • youbl
        • (水邊)
        • 等 級:
        #70樓 得分:0回復(fù)于:2011-12-12 13:53:08
        用Reflecor看了下4.0里的Monitor.Enter(object obj, ref bool lockTaken)方法
        最后是調(diào)用:
        [MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
        private static extern void ReliableEnter(object obj, ref bool lockTaken);
         
        想請教下,這個(gè)ReliableEnter方法能確保加鎖obj,并對lockTaken賦值為ture這2個(gè)操作是原子的嗎?
        而不會(huì)出現(xiàn)在加鎖后,線程Abort,沒來得及對lockTaken賦值?
        • xuStanly用戶頭像
        • xuStanly
        • (樓主深肖朕躬)
        • 等 級:
        #71樓 得分:0回復(fù)于:2011-12-12 14:37:37
        好棒的帖子.
        記號.
        #72樓 得分:0回復(fù)于:2011-12-12 14:40:10
        引用 70 樓 youbl 的回復(fù):

        用Reflecor看了下4.0里的Monitor.Enter(object obj, ref bool lockTaken)方法
        最后是調(diào)用:
        [MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
        private static extern void ReliableEnter(object obj, ref bool……

        finally塊會(huì)在調(diào)用Abort后線程中止前執(zhí)行(.net 1.0和1.1例外),看50樓代碼。
        • gomoku用戶頭像
        • gomoku
        • (IDynamicObject)
        • 等 級:
        #73樓 得分:0回復(fù)于:2011-12-12 14:46:32
        引用 70 樓 youbl 的回復(fù):
        ...這個(gè)ReliableEnter方法能確保加鎖objj,并對lockTaken賦值為ture這2個(gè)操作是原子的嗎

        這是個(gè)好問題,的確兩個(gè)操作必須在一個(gè)原子操作內(nèi)完成。
        可惜MethodImplOptions.InternalCall表明這個(gè)函數(shù)由CLR來負(fù)責(zé)實(shí)現(xiàn),我們不能直接檢查源碼。
        我選擇相信微軟會(huì)正確實(shí)現(xiàn),他的名字ReliableEnter(Reliable: 穩(wěn)妥)也暗示了實(shí)現(xiàn)方式。

          本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
          轉(zhuǎn)藏 分享 獻(xiàn)花(0

          0條評論

          發(fā)表

          請遵守用戶 評論公約

          類似文章 更多