Chapter09-内核模式下的线程同步之事件内核对象
?????? 有兩種事件內(nèi)核對象:自動(dòng)事件和手動(dòng)事件。當(dāng)手動(dòng)事件被觸發(fā)時(shí),所以該事件的等待線程都編程可調(diào)度狀態(tài);而自動(dòng)事件被觸發(fā)時(shí),只有個(gè)一個(gè)等待該事件線程變成可調(diào)度狀態(tài)。
?????? 下面再逐個(gè)講解Event的相關(guān)函數(shù):
a)???????創(chuàng)建事件函數(shù)——CreateEvent函數(shù):
?????????? HANDLE CreateEvent(
?????????????????????????????????? PSECURITY_ATTRIBUTESpsa,
?????????????????????????????????? BOOLbManualReset,
?????????????????????????????????? BOOLbInitialState,
?????????????????????????????????? PCTSTRpszName);
????????? 具體的函數(shù)參數(shù)及用法,請查看上面的超鏈接。
b)???????第二創(chuàng)建事件的函數(shù)——CreateEventEx函數(shù):
?????????? HANDLE CreateEventEx(
?????????????????????????????????? PSECURITY_ATTRIBUTESpsa,
?????????????????????????????????? PCTSTRpszName,
?????????????????????????????????? DWORDdwFlags,
?????????????????????????????????? DWORDdwDesiredAccess);
c)???????訪問某個(gè)打開的事件(Event)——OpenEvent函數(shù):
?????????? HANDLE OpenEvent(
?????????????????????????????????? DWORDdwDesiredAccess,
?????????????????????????????????? BOOLbInherit,
?????????????????????????????????? PCTSTRpszName)
????????? 在pszName傳遞創(chuàng)建事件時(shí)函數(shù)的pszName參數(shù)值。
d)???????使得某個(gè)事件處于觸發(fā)狀態(tài)——SetEvent函數(shù):
????????? BOOL SetEvent(HANDLE hEvent);
e)???????將某個(gè)事件設(shè)置為非觸發(fā)狀態(tài)——ResetEvent函數(shù):
????????? BOOL ResetEvent(HANDLE hEvent);
f)????????特別的函數(shù)——PluseEvent函數(shù):
????????? BOOL PulseEvent(HANDLE hEvent);
???????? 其作用相當(dāng)于在調(diào)用SetEvent函數(shù)后立即調(diào)用ResetEvent函數(shù),功能就是一次啟用一個(gè)線程。因?yàn)槭謩?dòng)方式的事件時(shí),當(dāng)事件觸發(fā)時(shí),所有的該事件阻塞的線程都會(huì)轉(zhuǎn)為可調(diào)度狀態(tài)。如果你調(diào)用PluseEvent函數(shù)后,在系統(tǒng)調(diào)用某一個(gè)線程后,由于立馬將事件設(shè)置為非觸發(fā)狀態(tài),這是其他線程也就再次被阻塞了。解釋起來好像比較麻煩,不過該函數(shù)在實(shí)際使用過程中也少有用到。
看一個(gè)創(chuàng)建事件時(shí)設(shè)置手動(dòng)方式的事件(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); }創(chuàng)建事件時(shí)設(shè)置為自動(dòng)方式時(shí)的事件(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); }??????
分析:
? ? ? 對比上面的代碼示例,細(xì)心的話你會(huì)發(fā)現(xiàn):在自動(dòng)方式下的代碼中,每個(gè)線程在返回前都會(huì)調(diào)用SetEvent函數(shù)將事件設(shè)置為觸發(fā)狀態(tài);而手動(dòng)方式事件對應(yīng)的函數(shù)中沒有調(diào)用這個(gè)函數(shù)。
? ? ? 這是因?yàn)?/span>在自動(dòng)方式下,事件每次轉(zhuǎn)化為觸發(fā)狀態(tài)時(shí)只能使一個(gè)線程變成可調(diào)度狀態(tài),為了讓其他線程也能被執(zhí)行,所以在每個(gè)線程返回前再次將事件設(shè)置為觸發(fā)狀態(tài),使得其他等待該事件的線程轉(zhuǎn)為可調(diào)度狀態(tài)從而被執(zhí)行。
? ? ? 而手動(dòng)方式下,則不同,當(dāng)手動(dòng)方式事件被SetEvent函數(shù)觸發(fā)一次,它就一直保持觸發(fā)態(tài),直到再次調(diào)用ReSetEvent函數(shù)將它設(shè)為非觸發(fā)態(tài)。
轉(zhuǎn)載于:https://www.cnblogs.com/java20130722/archive/2012/08/05/3207198.html
總結(jié)
以上是生活随笔為你收集整理的Chapter09-内核模式下的线程同步之事件内核对象的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux程序设计---序
- 下一篇: [无向图割点] PKU 1523 SPF