• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

            windows核心編程--線程的同步

            線程的同步
            由于同一進程的所有線程共享進程的虛擬地址空間,并且線程的中斷是匯編語言級的,所以可能會發(fā)生兩個線程同時訪問同一個對象(包括全局變量、共享資源、API函數(shù)和MFC對象等)的情況,這有可能導致程序錯誤。屬于不同進程的線程在同時訪問同一內(nèi)存區(qū)域或共享資源時,也會存在同樣的問題。因此,在多線程應用程序中,常常需要采取一些措施來同步線程的執(zhí)行。
            需要同步的情況包括以下幾種:

            在多個線程同時訪問同一對象時,可能產(chǎn)生錯誤。例如,如果當一個線程正在讀取一個至關重要的共享緩沖區(qū)時,另一個線程向該緩沖區(qū)寫入數(shù)據(jù),那么程序的運行結果就可能出錯。程序應該盡量避免多個線程同時訪問同一個緩沖區(qū)或系統(tǒng)資源。

            Windows 95環(huán)境下編寫多線程應用程序還需要考慮重入問題。Windows NT是真正的32位操作系統(tǒng),它解決了系統(tǒng)重入問題。而Windows 95由于繼承了Windows 3.x的部分16位代碼,沒能夠解決重入問題。這意味著在Windows 95中兩個線程不能同時執(zhí)行某個系統(tǒng)功能,否則有可能造成程序錯誤,甚至會造成系統(tǒng)崩潰。應用程序應該盡量避免發(fā)生兩個以上的線程同時調(diào)用同一個Windows API函數(shù)的情況。

            由于大小和性能方面的原因,

            MFC對象在對象級不是線程安全的,只有在類級才是。也就是說,兩個線程可以安全地使用兩個不同的CString對象,但同時使用同一個CString對象就可能產(chǎn)生問題。如果必須使用同一個對象,那么應該采取適當?shù)耐酱胧?

            多個線程之間需要協(xié)調(diào)運行。例如,如果第二個線程需要等待第一個線程完成到某一步時才能運行,那么該線程應該暫時掛起以減少對

            CPU的占用時間,提高程序的執(zhí)行效率。當?shù)谝粋€線程完成了相應的步驟后,應該發(fā)出某種信號來激活第二個線程。

            關鍵節(jié)和互鎖變量訪問

            關鍵節(jié) (Critical Seciton) mutex 的功能類似,但它只能由同一進程中的線程使用。關鍵節(jié)可以防止共享資源被同時訪問。

            進程負責為關鍵節(jié)分配內(nèi)存空間,關鍵節(jié)實際上是一個CRITICAL_SECTION型的變量,它一次只能被一個線程擁有。在線程使用關鍵節(jié)之前,必須調(diào)用InitializeCriticalSection函數(shù)將其初始化。如果線程中有一段關鍵的代碼不希望被別的線程中斷,那么可以調(diào)用EnterCriticalSection函數(shù)來申請關鍵節(jié)的所有權,在運行完關鍵代碼后再用LeaveCriticalSection函數(shù)來釋放所有權。如果在調(diào)用EnterCriticalSection時關鍵節(jié)對象已被另一個線程擁有,那么該函數(shù)將無限期等待所有權。

            利用互鎖變量可以建立簡單有效的同步機制。使用函數(shù)InterlockedIncrementInterlockedDecrement可以增加或減少多個線程共享的一個32位變量的值,并且可以檢查結果是否為0。線程不必擔心會被其它線程中斷而導致錯誤。如果變量位于共享內(nèi)存中,那么不同進程中的線程也可以使用這種機制。


            原子訪問

            所謂原子訪問,是指線程在訪問資源時能夠確保所有其他線程都不在同一時間內(nèi)訪問相同的資源?;ユi的函數(shù)家族:
            LONG InterlockedExchangeAdd(
               PLONG plAddend,
               LONG Increment);

            這是個最簡單的函數(shù)了。只需調(diào)用這個函數(shù),傳遞一個長變量地址,并指明將這個值遞增多少即可。但是這個函數(shù)能夠保證值的遞增以原子操作方式來完成。


            LONG InterlockedExchange(PLONG plTarget,
            LONG lValue);
            PVOID InterlockedExchangePointer(PVOID* ppvTarget,
            PVOID pvValue);

            I n t e r l o c k e d E x c h a n g e和I n t e r l o c k e d E x c h a n g e P o i n t e r能夠以原子操作方式用第二個參數(shù)中傳遞的值來取代第一個參數(shù)中傳遞的當前值。

                                                ------------------------------以上為用戶方式同步,以下為內(nèi)核方式同步---------------------------------

            等待函數(shù)

            等待函數(shù)可使線程自愿進入等待狀態(tài),直到一個特定的內(nèi)核對象變?yōu)橐淹ㄖ獱顟B(tài)為止。

            DWORD WaitForSingleObject(HANDLE hObject,
               DWORD dwMilliseconds);


            函數(shù)Wa i t F o r M u l t i p l e O b j e c t s與Wa i t F o r S i n g l e O b j e c t函數(shù)很相似,區(qū)別在于它允許調(diào)用線程同時查看若干個內(nèi)核對象的已通知狀態(tài):

             

            DWORD WaitForMultipleObjects(DWORD dwCount,
            CONST HANDLE* phObjects,
            BOOL fWaitAll,
            DWORD dwMilliseconds);



            同步對象

            同步對象用來協(xié)調(diào)多線程的執(zhí)行,它可以被多個線程共享。線程的等待函數(shù)用同步對象的句柄作為參數(shù),同步對象應該是所有要使用的線程都能訪問到的。同步對象的狀態(tài)要么是有信號的,要么是無信號的。同步對象主要有三種:事件、 mutex 和信號燈。

            事件對象 (Event) 是最簡單的同步對象,它包括有信號和無信號兩種狀態(tài)。在線程訪問某一資源之前,也許需要等待某一事件的發(fā)生,這時用事件對象最合適。例如,只有在通信端口緩沖區(qū)收到數(shù)據(jù)后,監(jiān)視線程才被激活。

            事件對象是用 CreateEvent 函數(shù)建立的。該函數(shù)可以指定事件對象的種類和事件的初始狀態(tài)。如果是手工重置事件,那么它總是保持有信號狀態(tài),直到用 ResetEvent 函數(shù)重置成無信號的事件。如果是自動重置事件,那么它的狀態(tài)在單個等待線程釋放后會自動變?yōu)闊o信號的。用 SetEvent 可以把事件對象設置成有信號狀態(tài)。在建立事件時,可以為對象起個名字,這樣其它進程中的線程可以用 OpenEvent 函數(shù)打開指定名字的事件對象句柄。

            mutex對象的狀態(tài)在它不被任何線程擁有時是有信號的,而當它被擁有時則是無信號的。mutex對象很適合用來協(xié)調(diào)多個線程對共享資源的互斥訪問(mutually exclusive)。

            線程用 CreateMutex 函數(shù)來建立 mutex 對象,在建立 mutex 時,可以為對象起個名字,這樣其它進程中的線程可以用 OpenMutex 函數(shù)打開指定名字的 mutex 對象句柄。在完成對共享資源的訪問后,線程可以調(diào)用 ReleaseMutex 來釋放 mutex ,以便讓別的線程能訪問共享資源。如果線程終止而不釋放 mutex ,則認為該 mutex 被廢棄。

            信號燈對象維護一個從 0 開始的計數(shù),在計數(shù)值大于 0 時對象是有信號的,而在計數(shù)值為 0 時則是無信號的。信號燈對象可用來限制對共享資源進行訪問的線程數(shù)量。線程用 CreateSemaphore 函數(shù)來建立信號燈對象,在調(diào)用該函數(shù)時,可以指定對象的初始計數(shù)和最大計數(shù)。在建立信號燈時也可以為對象起個名字,別的進程中的線程可以用 OpenSemaphore 函數(shù)打開指定名字的信號燈句柄。

            一般把信號燈的初始計數(shù)設置成最大值。每次當信號燈有信號使等待函數(shù)返回時,信號燈計數(shù)就會減 1 ,而調(diào)用 ReleaseSemaphore 可以增加信號燈的計數(shù)。計數(shù)值越小就表明訪問共享資源的程序越多。

            可用于同步的對象

            對象

            描述

            變化通知

            FindFirstChangeNotification 函數(shù)建立,當在指定目錄中發(fā)生指定類型的變化時對象變成有信號的。

            控制臺輸入

            在控制臺建立是被創(chuàng)建。它是用

            CONIN$ 調(diào)用 CreateFile 函數(shù)返回的句柄,或是 GetStdHandle 函數(shù)的返回句柄。如果控制臺輸入緩沖區(qū)中有數(shù)據(jù),那么對象是有信號的,如果緩沖區(qū)為空,則對象是無信號的。

            進程

            當調(diào)用

            CreateProcess 建立進程時被創(chuàng)建。進程在運行時對象是無信號的,當進程終止時對象是有信號的。

            線程

            當調(diào)用

            Createprocess 、 CreateThread CreateRemoteThread 函數(shù)創(chuàng)建新線程時被創(chuàng)建。在線程運行是對象是無信號的,在線程終止時則是有信號的。
            另外,有時可以用文件或通信設備作為同步對象使用。

            事件內(nèi)核對象

            讓我們觀察一個簡單的例子,以便說明如何使用事件內(nèi)核對象對線程進行同步。下面就是這個代碼:

             

            // Create a global handle to a manual-reset, nonsignaled event.
            HANDLE g_hEvent;
            int WINAPI WinMain(...)
            {
            //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)建一個人工重置的未通知狀態(tài)的事件,并且將句柄保存在一個全局變量中。這使得該進程中的其他線程能夠非常容易地訪問同一個事件對象?,F(xiàn)在3個線程已經(jīng)產(chǎn)生。這些線程要等待文件的內(nèi)容讀入內(nèi)存,然后每個線程都要訪問它的數(shù)據(jù)。一個線程進行單詞計數(shù),另一個線程運行拼寫檢查器,第三個線程運行語法檢查器。這3個線程函數(shù)的代碼的開始部分都相同,每個函數(shù)都調(diào)用Wa i t F o r S i n g l e O b j e c t,這將使線程暫停運行,直到文件的內(nèi)容由主線程讀入內(nèi)存為止。

            一旦主線程將數(shù)據(jù)準備好,它就調(diào)用S e t E v e n t,給事件發(fā)出通知信號。這時,系統(tǒng)就使所有這3個輔助線程進入可調(diào)度狀態(tài),它們都獲得了C P U時間,并且可以訪問內(nèi)存塊。注意,這3個線程都以只讀方式訪問內(nèi)存。這就是所有3個線程能夠同時運行的唯一原因。還要注意,如何計算機上配有多個C P U,那么所有3個線程都能夠真正地同時運行,從而可以在很短的時間內(nèi)完成大量的操作。

            如果你使用自動重置的事件而不是人工重置的事件,那么應用程序的行為特性就有很大的差別。當主線程調(diào)用S e t E v e n t之后,系統(tǒng)只允許一個輔助線程變成可調(diào)度狀態(tài)。同樣,也無法保證系統(tǒng)將使哪個線程變?yōu)榭烧{(diào)度狀態(tài)。其余兩個輔助線程將繼續(xù)等待。

            已經(jīng)變?yōu)榭烧{(diào)度狀態(tài)的線程擁有對內(nèi)存塊的獨占訪問權。讓我們重新編寫線程的函數(shù),使得每個函數(shù)在返回前調(diào)用S e t E v e n t函數(shù)(就像Wi n M a i n函數(shù)所做的那樣)。這些線程函數(shù)現(xiàn)在變成下面的形式:

             

            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);
            }
            當線程完成它對數(shù)據(jù)的專門傳遞時,它就調(diào)用S e t E v e n t函數(shù),該函數(shù)允許系統(tǒng)使得兩個正在等待的線程中的一個成為可調(diào)度線程。同樣,我們不知道系統(tǒng)將選擇哪個線程作為可調(diào)度線程,但是該線程將進行它自己的對內(nèi)存塊的專門傳遞。當該線程完成操作時,它也將調(diào)用S e t E v e n t函數(shù),使第三個即最后一個線程進行它自己的對內(nèi)存塊的傳遞。注意,當使用自動重置事件時,如果每個輔助線程均以讀/寫方式訪問內(nèi)存塊,那么就不會產(chǎn)生任何問題,這些線程將不再被要求將數(shù)據(jù)視為只讀數(shù)據(jù)。


            等待定時器內(nèi)核對象

            等待定時器是在某個時間或按規(guī)定的間隔時間發(fā)出自己的信號通知的內(nèi)核對象。它們通常用來在某個時間執(zhí)行某個操作。

            若要創(chuàng)建等待定時器,只需要調(diào)用C r e a t e Wa i t a b l e Ti m e r函數(shù):

             

            HANDLE CreateWaitableTimer(
            PSECURITY_ATTRIBUTES psa,
            BOOL fManualReset,
            PCTSTR pszName);
            進程可以獲得它自己的與進程相關的現(xiàn)有等待定時器的句柄,方法是調(diào)用O p e n Wa i t a b l e Ti m e r函數(shù):

             

            HANDLE OpenWaitableTimer(
            DWORD dwDesiredAccess,
            BOOL bInheritHandle,
            PCTSTR pszName);
            當發(fā)出人工重置的定時器信號通知時,等待該定時器的所有線程均變?yōu)榭烧{(diào)度線程。當發(fā)出自動重置的定時器信號通知時,只有一個等待的線程變?yōu)榭烧{(diào)度線程。

            等待定時器對象總是在未通知狀態(tài)中創(chuàng)建。必須調(diào)用S e t Wa i t a b l e Ti m e r函數(shù)來告訴定時器你想在何時讓它成為已通知狀態(tài):

             

            BOOL SetWaitableTimer(
            HANDLE hTimer,
            const LARGE_INTEGER *pDueTime,
            LONG lPeriod,
            PTIMERAPCROUTINE pfnCompletionRoutine,
            PVOID pvArgToCompletionRoutine,
            BOOL fResume);
            定時器函數(shù)外,最后還有一個C a n c e l Wa i t a b l e Ti m e r函數(shù):

             

            BOOL CancelWaitableTimer(HANDLE hTimer);
            這個簡單的函數(shù)用于取出定時器的句柄并將它撤消,這樣,除非接著調(diào)用S e t Wa i t a b l e Ti m e r函數(shù)以便重新設置定時器,否則定時器決不會進行報時。

            信標內(nèi)核對象

            信標內(nèi)核對象用于對資源進行計數(shù)。它們與所有內(nèi)核對象一樣,包含一個使用數(shù)量,但是它們也包含另外兩個帶符號的3 2位值,一個是最大資源數(shù)量,一個是當前資源數(shù)量。最大資源數(shù)量用于標識信標能夠控制的資源的最大數(shù)量,而當前資源數(shù)量則用于標識當前可以使用的資源的數(shù)量。

            信標的使用規(guī)則如下:

            • 如果當前資源的數(shù)量大于0,則發(fā)出信標信號。

            • 如果當前資源數(shù)量是0,則不發(fā)出信標信號。

            • 系統(tǒng)決不允許當前資源的數(shù)量為負值。

            • 當前資源數(shù)量決不能大于最大資源數(shù)量。

            下面的函數(shù)用于創(chuàng)建信標內(nèi)核對象:

            HANDLE CreateSemaphore(
            PSECURITY_ATTRIBUTE psa,
            LONG lInitialCount,
            LONG lMaximumCount,
            PCTSTR pszName);
            通過調(diào)用O p e n S e m a p h o r e函數(shù),另一個進程可以獲得它自己的進程與現(xiàn)有信標相關的句柄:

             

            HANDLE OpenSemaphore(
            DWORD fdwAccess,
            BOOL bInheritHandle,
            PCTSTR pszName);

            通過調(diào)用R e l e a s e S e m a p h o r e函數(shù),線程就能夠?qū)π艠说漠斍百Y源數(shù)量進行遞增:

             

            BOOL ReleaseSemaphore(
            HANDLE hsem,
            LONG lReleaseCount,
            PLONG plPreviousCount);
            互斥對象內(nèi)核對象

            互斥對象(m u t e x)內(nèi)核對象能夠確保線程擁有對單個資源的互斥訪問權。
            互斥對象有許多用途,屬于最常用的內(nèi)核對象之一。通常來說,它們用于保護由多個線程訪問的內(nèi)存塊。如果多個線程要同時訪問內(nèi)存塊,內(nèi)存塊中的數(shù)據(jù)就可能遭到破壞。互斥對象能夠保證訪問內(nèi)存塊的任何線程擁有對該內(nèi)存塊的獨占訪問權,這樣就能夠保證數(shù)據(jù)的完整性。

            互斥對象的使用規(guī)則如下:

            • 如果線程I D是0(這是個無效I D),互斥對象不被任何線程所擁有,并且發(fā)出該互斥對象的通知信號。

            • 如果I D是個非0數(shù)字,那么一個線程就擁有互斥對象,并且不發(fā)出該互斥對象的通知信號。

            • 與所有其他內(nèi)核對象不同, 互斥對象在操作系統(tǒng)中擁有特殊的代碼,允許它們違反正常的規(guī)則(后面將要介紹這個異常情況)。

            若要使用互斥對象,必須有一個進程首先調(diào)用C r e a t e M u t e x,以便創(chuàng)建互斥對象:

            HANDLE CreateMutex(
            PSECURITY_ATTRIBUTES psa,
            BOOL fInitialOwner,
            PCTSTR pszName);

            通過調(diào)用O p e n M u t e x,另一個進程可以獲得它自己進程與現(xiàn)有互斥對象相關的句柄:

             

            HANDLE OpenMutex(
            DWORD fdwAccess,
            BOOL bInheritHandle,
            PCTSTR pszName);

            一旦線程成功地等待到一個互斥對象,該線程就知道它已經(jīng)擁有對受保護資源的獨占訪問權。試圖訪問該資源的任何其他線程(通過等待相同的互斥對象)均被置于等待狀態(tài)中。當目前擁有對資源的訪問權的線程不再需要它的訪問權時,它必須調(diào)用R e l e a s e M u t e x函數(shù)來釋放該互斥對象:

             

            BOOL ReleaseMutex(HANDLE hMutex);

            該函數(shù)將對象的遞歸計數(shù)器遞減1。

            互斥對象與關鍵代碼段的比較

            就等待線程的調(diào)度而言,互斥對象與關鍵代碼段之間有著相同的特性。但是它們在其他屬性方面卻各不相同。表9 - 1對它們進行了各方面的比較。

             

            表9-1 互斥對象與關鍵代碼段的比較

            特性 互斥對象 關鍵代碼段
            運行速度
            是否能夠跨進程邊界來使用
            聲明 HANDLE hmtx; CRITICAL_SECTION cs;
            初始化 h m t x = C r e a t e M u t e x(N U L L,F(xiàn)A L S E,N U L L); I n i t i a l i z e C r i t i c a l S e c t i o n ( & e s );
            清除 C l o s e H a n d l e(h m t x); D e l e t e C r i t i c a l S e c t i o n(& c s);
            無限等待 Wa i t F o r S i n g l e O b j e c t(h m t x , I N F I N I T E); E n t e r C r i t i c a l S e c t i o n(& c s);
            0等待 Wa i t F o r S i n g l e O b j e c t Tr y(h m t x , 0); E n t e r C r i t i c a l S e c t i o n(& c s);
            任意等待 Wa i t F o r S i n g l e O b j e c t(h m t x , d w M i l l i s e c o n d s); 不能
            釋放 R e l e a s e M u t e x(h m t x); L e a v e C r i t i c a l S e c t i o n(& c s);
            是否能夠等待其他內(nèi)核對象 是(使用Wa i t F o r M u l t i p l e O b j e c t s或類似的函數(shù))

            線程同步對象速查表

            內(nèi)核對象與線程同步之間的相互關系
            對象 何時處于未通知狀態(tài) 何時處于已通知狀態(tài) 成功等待的副作用
            進程 當進程仍然活動時 當進程終止運行時(E x i t P r o c e s s,Te r m i n a t e P r o c e s s)
            線程 當線程仍然活動時 當線程終止運行時(E x i t T h r e a d,Te r m i n a t e T h r e a d)
            作業(yè) 當作業(yè)的時間尚未結束時 當作業(yè)的時間已經(jīng)結束時
            文件 當I / O請求正在處理時 當I / O請求處理完畢時
            控制臺輸入 不存在任何輸入 當存在輸入時
            文件修改通知 沒有任何文件被修改 當文件系統(tǒng)發(fā)現(xiàn)修改時 重置通知
            自動重置事件 R e s e t E v e n t , P u l s e - E v e n t或等待成功 當調(diào)用S e t E v e n t / P u l s e E v e n t時 重置事件
            人工重置事件 R e s e t E v e n t或P u l s e E v e n t 當調(diào)用S e t E v e n t / P u l s e E v e n t時
            自動重置等待定時器 C a n c e l Wa i t a b l e Ti m e r或等待成功 當時間到時(S e t Wa i t a b l e Ti m e r) 重置定時器
            人工重置等待定時器 C a n c e l Wa i t a b l e Ti m e r 當時間到時(S e t Wa i t a b l e Ti m e r)
            信標 等待成功 當數(shù)量> 0時(R e l e a s e S e m a p h o r e) 數(shù)量遞減1
            互斥對象 等待成功 當未被線程擁有時(R e l e a s e互斥對象) 將所有權賦予線程
            關鍵代碼段(用戶方式) 等待成功((Tr y)E n t e r C r i t i c a l S e c t i o n) 當未被線程擁有時(L e a v e C r i t i c a l S e c t i o n) 將所有權賦予線程


            其他的線程同步函數(shù)

            1 異步設備I / O使得線程能夠啟動一個讀操作或?qū)懖僮鳎遣槐氐却x操作或?qū)懖僮魍瓿?。例如,如果線程需要將一個大文件裝入內(nèi)存,那么該線程可以告訴系統(tǒng)將文件裝入內(nèi)存。然后,當系統(tǒng)加載該文件時,該線程可以忙于執(zhí)行其他任務,如創(chuàng)建窗口、對內(nèi)部數(shù)據(jù)結構進行初始化等等。當初始化操作完成時,該線程可以終止自己的運行,等待系統(tǒng)通知它文件已經(jīng)讀取。

            2 線程也可以調(diào)用Wa i t F o r I n p u t I d l e來終止自己的運行:

             

            DWORD WaitForInputIdle(
            HANDLE hProcess,
            DWORD dwMilliseconds);

            該函數(shù)將一直處于等待狀態(tài),直到h P r o c e s s標識的進程在創(chuàng)建應用程序的第一個窗口的線程中已經(jīng)沒有尚未處理的輸入為止。這個函數(shù)可以用于父進程。父進程產(chǎn)生子進程,以便執(zhí)行某些操作。
            3 線程可以調(diào)用M s g Wa i t F o r M u l t i p l e O b j e c t s或M s g Wa i t F o r M u l t i p l e O b j e c t s E x函數(shù),讓線程等待它自己的消息:

             

            DWORD MsgWaitForMultipleObjects(
            DWORD dwCount,
            PHANDLE phObjects,
            BOOL fWaitAll,
            DWORD dwMilliseconds,
            DWORD dwWakeMask);
            DWORD MsgWaitForMultipleObjectsEx(
            DWORD dwCount,
            PHANDLE phObjects,
            DWORD dwMilliseconds,
            DWORD dwWakeMask,
            DWORD dwFlags);

            這些函數(shù)與Wa i t F o r M u l t i p l e O b j e c t s函數(shù)十分相似。差別在于它們允許線程在內(nèi)核對象變成已通知狀態(tài)或窗口消息需要調(diào)度到調(diào)用線程創(chuàng)建的窗口中時被調(diào)度。

            4 Wi n d o w s將非常出色的調(diào)試支持特性內(nèi)置于操作系統(tǒng)之中。當調(diào)試程序啟動運行時,它將自己附加給一個被調(diào)試程序。該調(diào)試程序只需閑置著,等待操作系統(tǒng)將與被調(diào)試程序相關的調(diào)試事件通知它。調(diào)試程序通過調(diào)用Wa i t F o r D e b u g E v e n t函數(shù)來等待這些事件的發(fā)生:

             

            BOOL WaitForDebugEvent(
            PDEBUG_EVENT pde,
            DWORD dwMilliseconds);

            當調(diào)試程序調(diào)用該函數(shù)時,調(diào)試程序的線程終止運行,系統(tǒng)將調(diào)試事件已經(jīng)發(fā)生的情況通知調(diào)試程序,方法是允許調(diào)用的Wa i t F o r D e b u g E v e n t函數(shù)返回。

            5 S i n g l e O b j e c t A n d Wa i t函數(shù)用于在單個原子方式的操作中發(fā)出關于內(nèi)核對象的通知并等待另一個內(nèi)核對象:

             

            DWORD SingleObjectAndWait(
            HANDLE hObjectToSignal,
            HANDLE hObjectToWaitOn,
            DWORD  dwMilliseconds,
            BOOL   fAlertable);

            posted on 2006-09-14 15:08 夢在天涯 閱讀(2805) 評論(1)  編輯 收藏 引用 所屬分類: Windows API

            評論

            # re: windows核心編程--線程的同步 2006-09-14 16:02 夢在天涯

            接下來一章是<<windows核心編程>>作者自己寫的線程同步工具包,我現(xiàn)在還看不懂,不過,應該是很好的,大家可以下去自己研究嘍  回復  更多評論   

            公告

            EMail:itech001#126.com

            導航

            統(tǒng)計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1811126
            • 排名 - 5

            最新評論

            閱讀排行榜

            精品久久亚洲中文无码| 无码任你躁久久久久久| 国产精品99久久99久久久| 久久婷婷五月综合成人D啪| 亚洲精品国产自在久久| 欧美亚洲国产精品久久| 少妇人妻88久久中文字幕| 亚洲国产精品无码成人片久久| 日韩欧美亚洲综合久久| 久久久青草久久久青草| 亚洲人成网站999久久久综合| 一本久久a久久精品综合香蕉| 亚洲AV无码久久| 亚洲国产精品无码久久一线| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 精品国产VA久久久久久久冰| 99久久精品国产一区二区三区| 久久99国产精品久久99小说| 99久久亚洲综合精品网站| 2021最新久久久视精品爱 | 精品久久久无码中文字幕| 日日躁夜夜躁狠狠久久AV| 午夜精品久久影院蜜桃| 国产高清美女一级a毛片久久w| 狠狠色丁香久久婷婷综合| 欧美久久一区二区三区| 精品国产乱码久久久久久浪潮 | 久久无码人妻一区二区三区午夜 | 三上悠亚久久精品| 久久久久久国产精品美女| 一本久道久久综合狠狠躁AV| 女同久久| 性做久久久久久久久浪潮| 四虎影视久久久免费| 久久精品不卡| 久久天天躁狠狠躁夜夜2020老熟妇 | 久久久国产亚洲精品| 亚洲国产成人精品91久久久| 精品久久久久国产免费| 久久激情亚洲精品无码?V| 亚洲国产成人久久一区久久 |