青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cc

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  38 隨筆 :: 14 文章 :: 21 評論 :: 0 Trackbacks
隨著對多線程學習的深入,你可能覺得需要了解一些有關線程共享資源的問題. .NET framework提供了很多的類和數據類型來控制對共享資源的訪問。

  考慮一種我們經常遇到的情況:有一些全局變量和共享的類變量,我們需要從不同的線程來更新它們,可以通過使用System.Threading.Interlocked類完成這樣的任務,它提供了原子的,非模塊化的整數更新操作。

  還有你可以使用System.Threading.Monitor類鎖定對象的方法的一段代碼,使其暫時不能被別的線程訪問。

  System.Threading.WaitHandle類的實例可以用來封裝等待對共享資源的獨占訪問權的操作系統特定的對象。尤其對于非受管代碼的互操作問題。

  System.Threading.Mutex用于對多個復雜的線程同步的問題,它也允許單線程的訪問。

  像ManualResetEvent和AutoResetEvent這樣的同步事件類支持一個類通知其他事件的線程。

  不討論線程的同步問題,等于對多線程編程知之甚少,但是我們要十分謹慎的使用多線程的同步。在使用線程同步時,我們事先就要要能夠正確的確定是那個對象和方法有可能造成死鎖(死鎖就是所有的線程都停止了相應,都在等者對方釋放資源)。還有贓數據的問題(指的是同一時間多個線程對數據作了操作而造成的不一致),這個不容易理解,這么說吧,有X和Y兩個線程,線程X從文件讀取數據并且寫數據到數據結構,線程Y從這個數據結構讀數據并將數據送到其他的計算機。假設在Y讀數據的同時,X寫入數據,那么顯然Y讀取的數據與實際存儲的數據是不一致的。這種情況顯然是我們應該避免發生的。少量的線程將使得剛才的問題發生的幾率要少的多,對共享資源的訪問也更好的同步。

  .NET Framework的CLR提供了三種方法來完成對共享資源 ,諸如全局變量域,特定的代碼段,靜態的和實例化的方法和域。

  (1) 代碼域同步:使用Monitor類可以同步靜態/實例化的方法的全部代碼或者部分代碼段。不支持靜態域的同步。在實例化的方法中,this指針用于同步;而在靜態的方法中,類用于同步,這在后面會講到。

  (2) 手工同步:使用不同的同步類(諸如WaitHandle, Mutex, ReaderWriterLock, ManualResetEvent, AutoResetEvent 和Interlocked等)創建自己的同步機制。這種同步方式要求你自己手動的為不同的域和方法同步,這種同步方式也可以用于進程間的同步和對共享資源的等待而造成的死鎖解除。

  (3) 上下文同步:使用SynchronizationAttribute為ContextBoundObject對象創建簡單的,自動的同步。這種同步方式僅用于實例化的方法和域的同步。所有在同一個上下文域的對象共享同一個鎖。

Monitor Class

  在給定的時間和指定的代碼段只能被一個線程訪問,Monitor 類非常適合于這種情況的線程同步。這個類中的方法都是靜態的,所以不需要實例化這個類。下面一些靜態的方法提供了一種機制用來同步對象的訪問從而避免死鎖和維護數據的一致性。

  Monitor.Enter 方法:在指定對象上獲取排他鎖。

  Monitor.TryEnter 方法:試圖獲取指定對象的排他鎖。

  Monitor.Exit 方法:釋放指定對象上的排他鎖。

  Monitor.Wait 方法:釋放對象上的鎖并阻塞當前線程,直到它重新獲取該鎖。

  Monitor.Pulse 方法:通知等待隊列中的線程鎖定對象狀態的更改。

  Monitor.PulseAll 方法:通知所有的等待線程對象狀態的更改。

  通過對指定對象的加鎖和解鎖可以同步代碼段的訪問。Monitor.Enter, Monitor.TryEnter 和 Monitor.Exit用來對指定對象的加鎖和解鎖。一旦獲取(調用了Monitor.Enter)指定對象(代碼段)的鎖,其他的線程都不能獲取該鎖。舉個例子來說吧,線程X獲得了一個對象鎖,這個對象鎖可以釋放的(調用Monitor.Exit(object) or Monitor.Wait)。當這個對象鎖被釋放后,Monitor.Pulse方法和 Monitor.PulseAll方法通知就緒隊列的下一個線程進行和其他所有就緒隊列的線程將有機會獲取排他鎖。線程X釋放了鎖而線程Y獲得了鎖,同時調用Monitor.Wait的線程X進入等待隊列。當從當前鎖定對象的線程(線程Y)受到了Pulse或PulseAll,等待隊列的線程就進入就緒隊列。線程X重新得到對象鎖時,Monitor.Wait才返回。如果擁有鎖的線程(線程Y)不調用Pulse或PulseAll,方法可能被不確定的鎖定。Pulse, PulseAll and Wait必須是被同步的代碼段鄂被調用。對每一個同步的對象,你需要有當前擁有鎖的線程的指針,就緒隊列和等待隊列(包含需要被通知鎖定對象的狀態變化的線程)的指針。

  你也許會問,當兩個線程同時調用Monitor.Enter會發生什么事情?無論這兩個線程地調用Monitor.Enter是多么地接近,實際上肯定有一個在前,一個在后,因此永遠只會有一個獲得對象鎖。既然Monitor.Enter是原子操作,那么CPU是不可能偏好一個線程而不喜歡另外一個線程的。為了獲取更好的性能,你應該延遲后一個線程的獲取鎖調用和立即釋放前一個線程的對象鎖。對于private和internal的對象,加鎖是可行的,但是對于external對象有可能導致死鎖,因為不相關的代碼可能因為不同的目的而對同一個對象加鎖。

  如果你要對一段代碼加鎖,最好的是在try語句里面加入設置鎖的語句,而將Monitor.Exit放在finally語句里面。對于整個代碼段的加鎖,你可以使用MethodImplAttribute(在System.Runtime.CompilerServices命名空間)類在其構造器中設置同步值。這是一種可以替代的方法,當加鎖的方法返回時,鎖也就被釋放了。如果需要要很快釋放鎖,你可以使用Monitor類和C# lock的聲明代替上述的方法。

  讓我們來看一段使用Monitor類的代碼:

public void some_method()
{

int a=100;

int b=0;

Monitor.Enter(this);

//say we do something here.

int c=a/b;

Monitor.Exit(this);

}


  上面的代碼運行會產生問題。當代碼運行到int c=a/b; 的時候,會拋出一個異常,Monitor.Exit將不會返回。因此這段程序將掛起,其他的線程也將得不到鎖。有兩種方法可以解決上面的問題。第一個方法是:將代碼放入try…finally內,在finally調用Monitor.Exit,這樣的話最后一定會釋放鎖。第二種方法是:利用C#的lock()方法。調用這個方法和調用Monitoy.Enter的作用效果是一樣的。但是這種方法一旦代碼執行超出范圍,釋放鎖將不會自動的發生。見下面的代碼:

public void some_method()
{

int a=100;

int b=0;

lock(this);

//say we do something here.

int c=a/b;

}


  C# lock申明提供了與Monitoy.Enter和Monitoy.Exit同樣的功能,這種方法用在你的代碼段不能被其他獨立的線程中斷的情況。

WaitHandle Class

  WaitHandle類作為基類來使用的,它允許多個等待操作。這個類封裝了win32的同步處理方法。WaitHandle對象通知其他的線程它需要對資源排他性的訪問,其他的線程必須等待,直到WaitHandle不再使用資源和等待句柄沒有被使用。下面是從它繼承來的幾個類:

  Mutex 類:同步基元也可用于進程間同步。

  AutoResetEvent:通知一個或多個正在等待的線程已發生事件。無法繼承此類。

  ManualResetEvent:當通知一個或多個正在等待的線程事件已發生時出現。無法繼承此類。

  這些類定義了一些信號機制使得對資源排他性訪問的占有和釋放。他們有兩種狀態:signaled 和 nonsignaled。Signaled狀態的等待句柄不屬于任何線程,除非是nonsignaled狀態。擁有等待句柄的線程不再使用等待句柄時用set方法,其他的線程可以調用Reset方法來改變狀態或者任意一個WaitHandle方法要求擁有等待句柄,這些方法見下面:

  WaitAll:等待指定數組中的所有元素收到信號。

  WaitAny:等待指定數組中的任一元素收到信號。

  WaitOne:當在派生類中重寫時,阻塞當前線程,直到當前的 WaitHandle 收到信號。

  這些wait方法阻塞線程直到一個或者更多的同步對象收到信號。

  WaitHandle對象封裝等待對共享資源的獨占訪問權的操作系統特定的對象無論是收管代碼還是非受管代碼都可以使用。但是它沒有Monitor使用輕便,Monitor是完全的受管代碼而且對操作系統資源的使用非常有效率。


Mutex Class

  Mutex是另外一種完成線程間和跨進程同步的方法,它同時也提供進程間的同步。它允許一個線程獨占共享資源的同時阻止其他線程和進程的訪問。Mutex的名字就很好的說明了它的所有者對資源的排他性的占有。一旦一個線程擁有了Mutex,想得到Mutex的其他線程都將掛起直到占有線程釋放它。Mutex.ReleaseMutex方法用于釋放Mutex,一個線程可以多次調用wait方法來請求同一個Mutex,但是在釋放Mutex的時候必須調用同樣次數的Mutex.ReleaseMutex。如果沒有線程占有Mutex,那么Mutex的狀態就變為signaled,否則為nosignaled。一旦Mutex的狀態變為signaled,等待隊列的下一個線程將會得到Mutex。Mutex類對應與win32的CreateMutex,創建Mutex對象的方法非常簡單,常用的有下面幾種方法:

  一個線程可以通過調用WaitHandle.WaitOne 或 WaitHandle.WaitAny 或 WaitHandle.WaitAll得到Mutex的擁有權。如果Mutex不屬于任何線程,上述調用將使得線程擁有Mutex,而且WaitOne會立即返回。但是如果有其他的線程擁有Mutex,WaitOne將陷入無限期的等待直到獲取Mutex。你可以在WaitOne方法中指定參數即等待的時間而避免無限期的等待Mutex。調用Close作用于Mutex將釋放擁有。一旦Mutex被創建,你可以通過GetHandle方法獲得Mutex的句柄而給WaitHandle.WaitAny 或 WaitHandle.WaitAll 方法使用。

  下面是一個示例:

public void some_method()
{

int a=100;

int b=20;

Mutex firstMutex = new Mutex(false);

FirstMutex.WaitOne();

//some kind of processing can be done here.

Int x=a/b;

FirstMutex.Close();

}


  在上面的例子中,線程創建了Mutex,但是開始并沒有申明擁有它,通過調用WaitOne方法擁有Mutex。

Synchronization Events

  同步時間是一些等待句柄用來通知其他的線程發生了什么事情和資源是可用的。他們有兩個狀態:signaled and nonsignaled。AutoResetEvent 和 ManualResetEvent就是這種同步事件。


AutoResetEvent Class

  這個類可以通知一個或多個線程發生事件。當一個等待線程得到釋放時,它將狀態轉換為signaled。用set方法使它的實例狀態變為signaled。但是一旦等待的線程被通知時間變為signaled,它的轉臺將自動的變為nonsignaled。如果沒有線程偵聽事件,轉臺將保持為signaled。此類不能被繼承。


ManualResetEvent Class

  這個類也用來通知一個或多個線程事件發生了。它的狀態可以手動的被設置和重置。手動重置時間將保持signaled狀態直到ManualResetEvent.Reset設置其狀態為nonsignaled,或保持狀態為nonsignaled直到ManualResetEvent.Set設置其狀態為signaled。這個類不能被繼承。


Interlocked Class

  它提供了在線程之間共享的變量訪問的同步,它的操作時原子操作,且被線程共享.你可以通過Interlocked.Increment 或 Interlocked.Decrement來增加或減少共享變量.它的有點在于是原子操作,也就是說這些方法可以代一個整型的參數增量并且返回新的值,所有的操作就是一步.你也可以使用它來指定變量的值或者檢查兩個變量是否相等,如果相等,將用指定的值代替其中一個變量的值.


ReaderWriterLock class

  它定義了一種鎖,提供唯一寫/多讀的機制,使得讀寫的同步.任意數目的線程都可以讀數據,數據鎖在有線程更新數據時將是需要的.讀的線程可以獲取鎖,當且僅當這里沒有寫的線程.當沒有讀線程和其他的寫線程時,寫線程可以得到鎖.因此,一旦writer-lock被請求,所有的讀線程將不能讀取數據直到寫線程訪問完畢.它支持暫停而避免死鎖.它也支持嵌套的讀/寫鎖.支持嵌套的讀鎖的方法是ReaderWriterLock.AcquireReaderLock,如果一個線程有寫鎖則該線程將暫停;

  支持嵌套的寫鎖的方法是ReaderWriterLock.AcquireWriterLock,如果一個線程有讀鎖則該線程暫停.如果有讀鎖將容易倒是死鎖.安全的辦法是使用ReaderWriterLock.UpgradeToWriterLock方法,這將使讀者升級到寫者.你可以用ReaderWriterLock.DowngradeFromWriterLock方法使寫者降級為讀者.調用ReaderWriterLock.ReleaseLock將釋放鎖, ReaderWriterLock.RestoreLock將重新裝載鎖的狀態到調用ReaderWriterLock.ReleaseLock以前.


結論:

  這部分講述了.NET平臺上的線程同步的問題.造接下來的系列文章中我將給出一些例子來更進一步的說明這些使用的方法和技巧.雖然線程同步的使用會給我們的程序帶來很大的價值,但是我們最好能夠小心使用這些方法.否則帶來的不是受益,而將倒是性能下降甚至程序崩潰.只有大量的聯系和體會才能使你駕馭這些技巧.盡量少使用那些在同步代碼塊完成不了或者不確定的阻塞的東西,尤其是I/O操作;盡可能的使用局部變量來代替全局變量;同步用在那些部分代碼被多個線程和進程訪問和狀態被不同的進程共享的地方;安排你的代碼使得每一個數據在一個線程里得到精確的控制;不是共享在線程之間的代碼是安全的;在下一篇文章中我們將學習線程池有關的知識.

posted on 2006-12-07 15:05 醒目西西 閱讀(136) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            日韩视频―中文字幕| 男人插女人欧美| 欧美亚洲视频在线观看| 亚洲影音一区| 国产精品国产a| 亚洲综合大片69999| 亚洲精品久久久久久下一站| 开元免费观看欧美电视剧网站| 久久婷婷国产麻豆91天堂| 亚洲精品乱码| 99精品国产99久久久久久福利| 欧美刺激午夜性久久久久久久| 亚洲国产成人不卡| 一本久道久久久| 国产欧美日韩亚州综合| 欧美影院在线| 亚洲精品美女在线观看| 亚洲永久免费| 亚洲人妖在线| 国产日韩欧美成人| 欧美高清hd18日本| 日韩亚洲欧美一区| 久久精品理论片| 99天天综合性| 黑人巨大精品欧美黑白配亚洲| 欧美久久久久| 久久久xxx| 午夜国产一区| 在线视频中文亚洲| 亚洲国产欧美不卡在线观看| 久久国产精品一区二区三区四区| 91久久综合| 亚洲激情在线激情| 狠狠色狠色综合曰曰| 欧美日韩一卡二卡| 欧美韩国日本一区| 欧美精品电影在线| 欧美精品大片| 欧美视频在线观看免费| 欧美成人精品不卡视频在线观看 | 免费看av成人| 亚洲一区3d动漫同人无遮挡| 欧美成人精品影院| 美女视频黄免费的久久| 久久国产66| 久久九九精品99国产精品| 亚洲欧美在线看| 欧美日韩不卡视频| 欧美精品一区二区三区在线看午夜 | 国产精品九九| 国产精品久久99| 国产精品中文字幕欧美| 国产精品一区二区三区观看| 国产精品久久久久免费a∨大胸 | 久久九九全国免费精品观看| 一区二区三区欧美视频| 亚洲图片在线| 久久精品国产综合| 欧美成人午夜剧场免费观看| 欧美激情视频网站| 国产精品久久久久久久app| 国产欧美在线观看| 亚洲人精品午夜| 午夜视频久久久| 免费日韩一区二区| 亚洲午夜激情| 噜噜噜躁狠狠躁狠狠精品视频| 国产精品vvv| 亚洲国产成人精品女人久久久| 一区二区三区视频免费在线观看| 久久se精品一区精品二区| 亚洲二区在线视频| 午夜在线电影亚洲一区| 欧美日韩久久久久久| 在线看成人片| 久久永久免费| 香蕉成人久久| 国产精品国产a级| 亚洲精品小视频在线观看| 久久成人18免费网站| 在线视频日韩| 欧美日韩一区二区精品| 亚洲国产清纯| 在线视频成人| 久久久青草婷婷精品综合日韩| 一本一本久久a久久精品综合妖精| 免费在线观看一区二区| 亚洲电影免费观看高清完整版| 欧美影视一区| 一区二区欧美激情| 欧美视频日韩视频| 亚洲一区二区三区中文字幕在线| 999亚洲国产精| 亚洲欧美日韩在线播放| 亚洲国产欧美另类丝袜| 欧美在线视频观看| 亚洲第一福利社区| 亚洲激情网站免费观看| 欧美精品久久久久久久久久| 一区二区av在线| 亚洲视频专区在线| 国产一区三区三区| 欧美激情精品| 国产精品高清在线| 久久尤物视频| 欧美精品色网| 久久精品水蜜桃av综合天堂| 久久精品2019中文字幕| 亚洲精品日韩精品| 亚洲夜晚福利在线观看| 在线播放国产一区中文字幕剧情欧美 | 亚洲男人第一网站| 永久91嫩草亚洲精品人人| 亚洲激情专区| 国产一区二区日韩精品欧美精品| 欧美国产日韩一区二区| 国产精品久久二区二区| 蜜桃av久久久亚洲精品| 国产精品久久久久9999| 欧美大成色www永久网站婷| 亚洲欧美久久久| 麻豆91精品91久久久的内涵| 亚洲视频电影在线| 麻豆精品在线视频| 国产模特精品视频久久久久| 久久字幕精品一区| 亚洲精品久久久久久一区二区 | 久久久久高清| 蜜臀av在线播放一区二区三区| 欧美三日本三级少妇三99| 久久影院午夜论| 国产曰批免费观看久久久| 99天天综合性| 日韩系列欧美系列| 欧美精品亚洲二区| 亚洲精品午夜| 亚洲综合久久久久| 国产精品高潮呻吟| 亚洲免费视频网站| 久久国产免费看| 国产一区二区av| 久久一区欧美| 亚洲精品在线看| 亚洲一区二区精品| 国产色视频一区| 蜜臀a∨国产成人精品| 最新国产精品拍自在线播放| 日韩五码在线| 国产小视频国产精品| 裸体素人女欧美日韩| 亚洲伦理自拍| 欧美影院午夜播放| 亚洲国产欧美日韩| 国产精品网曝门| 亚洲少妇自拍| 亚洲欧美日韩一区二区| 国产区日韩欧美| 久久免费视频在线观看| 亚洲人成在线播放| 欧美一区免费视频| 亚洲六月丁香色婷婷综合久久| 国产精品豆花视频| 欧美国产精品人人做人人爱| 亚洲欧美在线观看| 亚洲毛片一区二区| 美女图片一区二区| 欧美一级淫片aaaaaaa视频| 亚洲理伦在线| 亚洲国产精品尤物yw在线观看 | 亚洲国产精品va在线看黑人| 国产精品jizz在线观看美国| 老司机67194精品线观看| 午夜精品99久久免费| 日韩一区二区精品在线观看| 欧美国产日韩精品免费观看| 久久精品国产一区二区三区| 午夜一区二区三区在线观看| 在线视频你懂得一区二区三区| 亚洲国产精品传媒在线观看| 国内外成人免费视频 | 狠狠色狠狠色综合日日91app| 欧美性视频网站| 国产精品高清网站| 国产欧美日韩免费| 国产一区二区三区免费不卡| 国产一区999| 亚洲精品免费在线播放| 制服丝袜激情欧洲亚洲| 亚洲一区二区三区三| 美女精品网站| 欧美日韩中文字幕在线视频| 欧美性猛交xxxx乱大交蜜桃| 国产精品无人区| 91久久精品国产91久久性色| 亚洲午夜免费福利视频| 国产视频久久| 亚洲精品字幕| 小黄鸭精品aⅴ导航网站入口| 亚洲午夜影视影院在线观看| 性一交一乱一区二区洋洋av|