.NET简谈组件程序设计之(手动同步)
在上一篇文章“.NET簡談組件程序設計之(上下文與同步域) ”中,我們學習了關于一些上下文和同步域的概念,可以利用這兩個技術來進行自動同步。
今天我們主要學習怎么手動來執行同步,能從更小的粒度進行封鎖,以達到最大程度的吞吐量。[王清培版權所有,轉載請給出署名]
我們知道線程是進程的運行實體,進程是資源分配單位,而線程是執行單位。照書上所說,線程是程序的執行路徑,當我們分配一個線程的時候,要確定線程的執行路徑是什么,也就是代碼中的ThreadStart委托所指向的入口點方法。
一旦我們手動Start啟動線程的時候,當前上下文線程就被系統立即切換,我們從Thread.CurrentThread靜態屬性中可以準確的獲取到當前正在執行的線程實例,然后進行一系列的設置、等待、終止。[王清培版權所有,轉載請給出署名]
那么線程到底是怎么實現同步(互斥)的呢,在我們正常的代碼中是沒有關于線程同步的現實代碼的,所以在線程執行路徑中是不存在任何能夠阻塞線程的實現代碼。要想實現線程阻塞,就必須在線程的執行路徑中寫點東西,讓所有線程當進入這段代碼的時候(也就是臨界資源),通過判斷某種東西來確定是否允許進入執行。
圖1:
在ThreadStartEnterPoint方法中,如果沒有任何的同步代碼,那么任何線程都能進去執行,就導致了亂七八糟的數據。當數據在內存中的時候,在同一時間只能是由CPU去執行線程的代碼,但是線程是有競爭情況的,當線程1還沒有完全執行完畢,線程2就來執行這塊數據,導致數據的不同步。
那么我們需要再線程1還沒有執行完畢前不允許其他線程使用這塊內存對象。當線程1使用完后就立即釋放所占有的資源,讓其他線程能競爭。
利用Monitor(監視器)來進行同步
Monitor是用來提供同步的對象,通過它可以在某個時間點上鎖定對象。請看代碼:
這是一個類中的兩個方法,在方法的頭部我用了MethodImpl方法特性進行了標識,其實這個特性的目的就是在方法的入口處和結束處加上同步方法,也就是Monitor.Enter和Monitor.Exit,一般情況下我們都是習慣用lock來鎖定對象,其實lock也是Monitor的變體。這里我就不寫出來了。讓我們熟悉一下陌生的使用方式。
在調用的代碼里面,大概意思是這樣的,我們同時開啟兩個線程,入口點分別是上面的兩個方法,在PluseThread里面是為了將ShowMessage線程1從等待隊列里釋放出來繼續執行。[王清培版權所有,轉載請給出署名]
在ShowMessage里面我用Monitor.Wait方法等待,當調用這個方法的時候會使用我鎖定的對象,讓其他線程進入執行。當Monitor.Pluse的時候,線程1繼續執行。
靜態Monitor對象是每個線程都會執行的路徑,我們通過控制Monitor來進行線程同步,當我們調用Wait就是等待,直到當前對象Pluse才繼續執行。
圖2:
利用WaitHandle(等待句柄)來進行同步
上面我們通過Monitor來進行同步,在同步的時候我們需要很好的控制等待時間,用Monitor也能通過Wait進行等待超時設置,也許它內部封裝是Windows等待句柄。
這里我們通過使用WaitHandle來進行同步,WaitHandle是個抽象類,它的子類有很多,比如Mutex互斥體、ManualResetEvent、AutoResetEvent事件對象,等等。下面我們就來看看利用這些對象怎么同步線程。
Mutext互斥體
在方法的內部我們申請一個Mutex對象,這個Mutex是全局的,就是在一臺機器上只能存在一個名稱的Mutex,Mutex可用來同步線程也可以用來同步進程。
我們在Print方法里面用WaitOne獲取句柄,如果已經有線程“捷足先得”了,那么這里將阻塞,并返回false。
在使用完后,記得調用ReleaseMutex釋放當前占用的Mutex句柄。
圖3:
利用ManualResetEvent(手動事件)來進行同步
我們直接看代碼吧,ManualResetEvent大家可能都用過。
這種類型的等待句柄對象是完全手動控制的,讓我們想要用的時候要記得set,想要暫停的時候就Reset,不用了就close。
圖4:
利用AutoResetEvent(自動事件)來進行同步
從名字上就能看出,該事件是自動重置事件,不需要想上面那樣進行set\reset操作。
在上面的代碼中,我們通過WaitOne獲取等待句柄,當我們獲取到之后,事件對象會自動重置為信號已發,其他線程無法獲取到等待句柄。當我們set之后其他線程才能獲取到,這里省掉的是線程進入執行路徑的過程。
ManualResetEvent需要手動進行set才能使用,一旦set之后信號標記為未發狀態,所有線程都能執行代碼,除非手動Reset才能阻塞。
圖5:
[王清培版權所有,轉載請給出署名]
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的.NET简谈组件程序设计之(手动同步)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 敏捷开发与中医理论系列之一:序言及为何中
- 下一篇: 屏蔽键盘的钩子