Windows核心編程 - 用內核對象進行線程同步

        在上一篇文章Windows核心編程-用戶模式下的線程同步中已總結了用戶模式下的幾種同步機制,它們的特點就是速度快,但也有些侷限性。那麼與用戶模式的同步機制相對的,可以使用內核對象進行同步,既然是內核對象,那麼就涉及到用戶模式與內核模式切換,所以內核對象同步機制的缺點是會有性能問題,但它們的用途會更廣一些,例如可以實現進程間的同步。

        同步,其實是一方A需要感知另一方B的狀態,以便採取相應的措施(是繼續在此等待呢還是開始往下執行)。對於線程、進程等內核對象來說,它們要麼是處理觸發狀態,要麼處理未觸發狀態。 Microsoft爲每種對象創建了一些規則,規定如何在這兩種狀態之間進行切換。線程或進程內核對象在創建的時候總是處理未觸發狀態,當線程或進程終止時,狀態才改爲觸發。而且當狀態變成觸發後,將永遠保持這種狀態,不會再回到未觸發狀態。因此,可以通過調用一個等待函數,由系統來檢查目標內核對象的狀態,當狀態發生變化時等待函數返回,調用方檢查返回結果,採取進一步的措施,以實現同步。

1. 事件內核對象

       事件內核對象是比較簡單的一種,它內部有一個用來表示是自動重置事件還是手動重置事件的布爾值,以及一個用來表示事件有沒有被觸發的布爾值。有兩種類型的事件對象:手動重置事件和自動重置事件,兩者區別:

        1)當一個手動重置事件被觸發時,正在等待該事件的所有線程都會變成可調度狀態。

        2)當一個自動重置事件被觸發時,只會有一個正在等待該事件的線程變成可調度狀態,如果有多個正在等待該事件的線程,則不確定是哪一個線程會變成可調度狀態。

       把事件變成觸發狀態,使用SetEvent(); 把事件變成未觸發狀態,使用ResetEvent()。

      事件最通常的用途是:讓一個線程執行初始化工作,然後再觸發另一個線程,讓它執行剩餘的工作。

2.信號量內核對象

        信號量內核對象用來對資源進行計數,與其它內核對象不同的是它內部有兩個32位值:一個是最大資源計數,另一個是當前可用資源計數。最大資源計數表示信號量可以控制的最大資源數量,當前可用資源計數表示信號量當前可用資源的計數。

        信號量的規則如下:

        1)如果 當前可用資源計數大於0, 那麼信號量處於觸發狀態;

         2)如果當前可用資源計數等於0,那麼信號量處於未觸發狀態;

         3)系統絕對不會讓當前可用資源計數變爲負數;

         4)當前可用資源計數絕對不會大於最大資源計數。

         信號量最大的優勢是會以原子方式來對資源計數進行檢查及設置操作。比方說,當向信號量請求一個資源時,系統會檢查資源是否還夠,如果資源足夠,則將可用資源計數遞減,整個過程不會被其它線程打斷。

         應用: 多線程訪問共享資源的數量有限制的,可考慮使用信號量機制。

3.互斥量內核對象

         互斥量內核對象用於確保一個線程對一個資源的獨佔訪問。它內部包含一個線程ID和一個遞歸計數。線程ID用於標識 當前佔用這個互斥量的是哪個線程,遞歸計數表示這個線程佔用該互斥量的次數。

         互斥量與關鍵段的行爲類似,但是互斥量比關鍵段要慢,因爲它需進入到內核模式。但互斥量可以實現進程間的同步,即不同進程中的線程可以訪問同一個互斥量。

         互斥量的規則:

        1)如果線程ID爲0(無效線程ID),那麼該互斥量不爲任何線程所佔用,它處於觸發狀態;

        2)如果線程ID爲非零值,那麼有一個線程已經佔用了該互斥量,它處於未觸發狀態;

        應用:一般用來對多個線程訪問的同一塊內存進行保護。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章