1. 程式人生 > >C++訊號量Semaphore和MFC中的CSemaphore類使用【轉】

C++訊號量Semaphore和MFC中的CSemaphore類使用【轉】

信 號量(Semaphore )核心物件對執行緒的同步方式與前面幾種方法不同,它允許多個執行緒在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最 大執行緒數目。在用CreateSemaphore () 建立訊號量時即要同時指出允許的最大資源計數和當前可用資源計數。一般是將當前可用資源計數設定為最 大資源計數,每增加一個執行緒對共享資源的訪問,當前可用資源計數就會減1 ,只要當前可用資源計數是大於0 的,就可以發出訊號量訊號。但是當前可用計數減小 到0 時則說明當前佔用資源的執行緒數已經達到了所允許的最大數目,不能在允許其他執行緒的進入,此時的訊號量訊號將無法發出。執行緒在處理完共享資源後,應在離 開的同時通過ReleaseSemaphore
()函式將當前可用資源計數加1 。在任何時候當前可用資源計數決不可能大於最大資源計數。 訊號量是通過計數來對執行緒訪問資源進行控制的,而實際上訊號量確實也被稱作Dijkstra 計數器。 使用訊號量核心物件進行執行緒同步主要會用到CreateSemaphore ()、OpenSemaphore ()、 ReleaseSemaphore ()、WaitForSingleObject ()和WaitForMultipleObjects ()等函式。其 中,CreateSemaphore ()用來建立一個訊號量核心物件,其函式原型為:
HANDLE CreateSemaphore(
 LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //
安全屬性指標  LONG lInitialCount, // 初始計數  LONG lMaximumCount, // 最大計數  LPCTSTR lpName // 物件名指標
);
引數lMaximumCount 是一個有符號32 位值,定義了允許的最大資源計數,最大取值不能超過4294967295lpName 引數可以為建立的 訊號量定義一個名字,由於其建立的是一個核心物件,因此在其他程序中可以通過該名字而得到此訊號量。OpenSemaphore ()函式即可用來根據訊號 量名開啟在其他程序中建立的訊號量,函式原型如下:
HANDLE OpenSemaphore(
 DWORD dwDesiredAccess, //
訪問標誌  BOOL bInheritHandle, // 繼承標誌  LPCTSTR lpName // 訊號量名
);
線上程離開對共享資源的處理時,必須通過ReleaseSemaphore ()來增加當前可用資源計數。否則將會出現當前正在處理共享資源的實際執行緒數並 沒有達到要限制的數值,而其他執行緒卻因為當前可用資源計數為0 而仍無法進入的情況。ReleaseSemaphore ()的函式原型為:
BOOL ReleaseSemaphore(
 HANDLE hSemaphore, // 訊號量控制代碼  LONG lReleaseCount, // 計數遞增數量  LPLONG lpPreviousCount // 先前計數
);
該函式將lReleaseCount 中的值新增給訊號量的當前資源計數,一般將lReleaseCount 設定為1 ,如果需要也可以設定其他的值。 WaitForSingleObject ()和WaitForMultipleObjects ()主要用在試圖進入共享資源的執行緒函式入口處,主要用來判 斷訊號量的當前可用資源計數是否允許本執行緒的進入。只有在當前可用資源計數值大於0 時,被監視的訊號量核心物件才會得到通知。 訊號量的使用特點使其更適用於對Socket (套接字)程式中執行緒的同步。例如,網路上的HTTP 伺服器要對同一時間內訪問同一頁面的使用者數加以限制,這 時可以為每一個使用者對伺服器的頁面請求設定一個執行緒,而頁面則是待保護的共享資源,通過使用訊號量對執行緒的同步作用可以確保在任一時刻無論有多少使用者對某 一頁面進行訪問,只有不大於設定的最大使用者數目的執行緒能夠進行訪問,而其他的訪問企圖則被掛起,只有在有使用者退出對此頁面的訪問後才有可能進入。下面給出 的示例程式碼即展示了類似的處理過程: