Chapter09-内核模式下的线程同步之事件内核对象
?????? 有兩種事件內核對象:自動事件和手動事件。當手動事件被觸發時,所以該事件的等待線程都編程可調度狀態;而自動事件被觸發時,只有個一個等待該事件線程變成可調度狀態。
?????? 下面再逐個講解Event的相關函數:
a)???????創建事件函數——CreateEvent函數:
?????????? HANDLE CreateEvent(
?????????????????????????????????? PSECURITY_ATTRIBUTESpsa,
?????????????????????????????????? BOOLbManualReset,
?????????????????????????????????? BOOLbInitialState,
?????????????????????????????????? PCTSTRpszName);
????????? 具體的函數參數及用法,請查看上面的超鏈接。
b)???????第二創建事件的函數——CreateEventEx函數:
?????????? HANDLE CreateEventEx(
?????????????????????????????????? PSECURITY_ATTRIBUTESpsa,
?????????????????????????????????? PCTSTRpszName,
?????????????????????????????????? DWORDdwFlags,
?????????????????????????????????? DWORDdwDesiredAccess);
c)???????訪問某個打開的事件(Event)——OpenEvent函數:
?????????? HANDLE OpenEvent(
?????????????????????????????????? DWORDdwDesiredAccess,
?????????????????????????????????? BOOLbInherit,
?????????????????????????????????? PCTSTRpszName)
????????? 在pszName傳遞創建事件時函數的pszName參數值。
d)???????使得某個事件處于觸發狀態——SetEvent函數:
????????? BOOL SetEvent(HANDLE hEvent);
e)???????將某個事件設置為非觸發狀態——ResetEvent函數:
????????? BOOL ResetEvent(HANDLE hEvent);
f)????????特別的函數——PluseEvent函數:
????????? BOOL PulseEvent(HANDLE hEvent);
???????? 其作用相當于在調用SetEvent函數后立即調用ResetEvent函數,功能就是一次啟用一個線程。因為手動方式的事件時,當事件觸發時,所有的該事件阻塞的線程都會轉為可調度狀態。如果你調用PluseEvent函數后,在系統調用某一個線程后,由于立馬將事件設置為非觸發狀態,這是其他線程也就再次被阻塞了。解釋起來好像比較麻煩,不過該函數在實際使用過程中也少有用到。
看一個創建事件時設置手動方式的事件(manual-reset events)示例:
// Create a global handle to a manual-reset, nonsignaled event. HANDLE g_hEvent; int WINAPI _tWinMain(...) { // Create the manual-reset, nonsignaled event. g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Spawn 3 new threads. HANDLE hThread[3]; DWORD dwThreadID; hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID); hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID); hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID); OpenFileAndReadContentsIntoMemory(...); // Allow all 3 threads to access the memory. SetEvent(g_hEvent); ... } DWORD WINAPI WordCount(PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); } DWORD WINAPI SpellCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); } DWORD WINAPI GrammarCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... return(0); }創建事件時設置為自動方式時的事件(auto-reset event)示例:
// Create a global handle to a auto-reset, nonsignaled event. HANDLE g_hEvent; int WINAPI _tWinMain(...) { // Create the auto-reset, nonsignaled event. g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // Spawn 3 new threads. HANDLE hThread[3]; DWORD dwThreadID; hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID); hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID); hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID); OpenFileAndReadContentsIntoMemory(...); // Allow all 3 threads to access the memory. SetEvent(g_hEvent); ... } DWORD WINAPI WordCount(PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); } DWORD WINAPI SpellCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); } DWORD WINAPI GrammarCheck (PVOID pvParam) { // Wait until the file's data is in memory. WaitForSingleObject(g_hEvent, INFINITE); // Access the memory block. ... SetEvent(g_hEvent); return(0); }??????
分析:
? ? ? 對比上面的代碼示例,細心的話你會發現:在自動方式下的代碼中,每個線程在返回前都會調用SetEvent函數將事件設置為觸發狀態;而手動方式事件對應的函數中沒有調用這個函數。
? ? ? 這是因為在自動方式下,事件每次轉化為觸發狀態時只能使一個線程變成可調度狀態,為了讓其他線程也能被執行,所以在每個線程返回前再次將事件設置為觸發狀態,使得其他等待該事件的線程轉為可調度狀態從而被執行。
? ? ? 而手動方式下,則不同,當手動方式事件被SetEvent函數觸發一次,它就一直保持觸發態,直到再次調用ReSetEvent函數將它設為非觸發態。
轉載于:https://www.cnblogs.com/java20130722/archive/2012/08/05/3207198.html
總結
以上是生活随笔為你收集整理的Chapter09-内核模式下的线程同步之事件内核对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux程序设计---序
- 下一篇: [无向图割点] PKU 1523 SPF