免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Windows線程同步與互斥技術總結
1.1    線程同步概述
如果沒有同步對象和操作系統(tǒng)對特殊事件監(jiān)視的能力,線程可能被迫使用有副作用的技術使自己與特殊事件同步。不使用操作系統(tǒng)支持的線程同步技術,會產生許多問題,比如:分配不必要的CPU時間,浪費;在高低優(yōu)先級線程間,若低線程負責信號重置任務,則可能永遠無法執(zhí)行重置。
 
1.2    臨界區(qū)
1.2.1   概述
臨界區(qū):在所有同步對象中,臨界區(qū)是最容易使用的,但它只能用于同步單個進程中的線程。臨界區(qū)一次只允許一個線程取得對某個數(shù)據(jù)區(qū)的訪問權。還有,在這些同步對象中,只有臨界區(qū)不是內核對象,它不由操作系統(tǒng)的低級部件管理,而且不能使用句柄來操縱
 
1.         在進程中創(chuàng)建一個臨界區(qū),即在進程中分配一個CRITICAL_SECTION數(shù)據(jù)結構,該臨界區(qū)結構的分配必須是全局的,這樣該進程的不同線程就能訪問它。
2.         在使用臨界區(qū)同步線程之前,必須調用InitializeCriticalSection來初始化臨界區(qū)。在釋放資源之前,只需要初始化一次。
3.         VOID EnterCriticalSection:阻塞函數(shù)。The function returns when the calling thread is granted ownership。換言之,調用線程不能獲取指定臨界區(qū)的所有權時,該線程將睡眠,且在被喚醒之前,系統(tǒng)不會給它分配CPU。
4.         執(zhí)行臨界區(qū)內的任務
5.         BOOL LeaveCriticalSection:非阻塞函數(shù)。將當前線程對指定臨界區(qū)的引用計數(shù)減壹;在使用計數(shù)變?yōu)榱銜r,另一等待此臨界區(qū)的一個線程將被喚醒。
6.         當不需要再使用該臨界區(qū)時,使用DeleteCriticalSection來釋放臨界區(qū)需要的資源。此函數(shù)執(zhí)行后,再也不能使用EnterCriticalSection和LeaveCriticalSection,除非再次使用InitializeCriticalSection初始化了該臨界區(qū)。
 
 
1.2.2   注意事項:
1.         臨界區(qū)一次只允許一個線程訪問,每個線程必須在視圖操作臨界區(qū)域數(shù)據(jù)之前調用該臨界區(qū)域標志(即一個CRITICAL_SECTION全局變量)EnterCriticalSection后,其它想要獲得訪問權的線程都會置于睡眠狀態(tài),且在被喚醒以前,系統(tǒng)將停止為它們分配CPU時間片。換言之,臨界區(qū)可以且僅可被一個線程擁有,當然,沒有任何線程調用EnterCriticalSection或TryEnterCriticalSection時,臨界區(qū)不屬于任何一個線程。
2.         當擁有臨界區(qū)所有權的線程調用LeaveCriticalSection放棄所有權時,系統(tǒng)只喚醒正等待中的一個線程,給它所有權,其它線程則繼續(xù)睡眠。
3.         注意,擁有該臨界區(qū)的線程,每一次針對此臨界區(qū)的EnterCriticalSection調用都會成功(這里指的是重復調用也會立即返回),且會使得臨界區(qū)標志(即一個CRITICAL_SECTION全局變量)的引用計數(shù)增壹。在另一個線程能夠擁有該臨界區(qū)之前,擁有它的線程必須調用LeaveCriticalSection足夠多次,在引用計數(shù)降為零后,另一線程才有可能擁有該臨界區(qū)。換言之,在一個正常使用臨界區(qū)的線程中,calSection和LeaveCriticalSection應該成對使用。
1.3    用內核對象同步線程
1.3.1   概述
臨界區(qū)非常適合于序列化對一個進程中的數(shù)據(jù)的訪問,因為它們的速度很快。但我們或許想要使一些應用程序與計算機中發(fā)生的其它特殊事件或者其它進程中執(zhí)行的操作取得同步。這時臨界區(qū)無能為力。就需要使用內核對象來同步。
 
下列內核對象可用來同步線程:
1.         進程,Processes
2.         線程,Threads
3.         文件,F(xiàn)iles
4.         控制臺輸入,Console input
5.         文件變化通知,F(xiàn)ile change notifications
6.         互斥量,Mutexes
7.         信號量,Semaphores
8.         事件(自動重設事件和手動重設事件),Events
9.         可等的計時器(只用于Window NT4或更高),Waitable timers
10.     Jobs
 
每一個上面這些類型的對象都可以處于兩種狀態(tài)之一:有信號(signaled)和無信號(nonsignaled)。比如進程和線程在終結時其內核對象變?yōu)橛行盘?,而在它們處于?chuàng)建和正在運行時,其內核對象是無信號的。
 
1.3.2   內核對象同步應用
1.         某線程獲得某進程的內核對象句柄時,它可以:改變進程優(yōu)先級、獲得進程的退出碼;使本線程與某進程的終結取得同步等等。
2.         當獲得某線程的內核對象句柄時,它可以:改變該線程運行狀態(tài)、與該線程的終結取得同步等等。
3.         當獲得文件句柄時,也可以:本線程可與某一個異步文件的I/O操作獲得同步等等。
4.         控制臺輸入對象可用來使線程在有輸入進入時被喚醒以執(zhí)行相關任務等等。
5.         其它內核對象―――文件改變通知、互斥量、信號量、事件、可等計時器等―――都只是為了同步對象而存在。相應的,也有WIN32函數(shù)來創(chuàng)建、打開、關閉這些對象,將線程與這些對象同步。對這些對象,沒有其它操作可以執(zhí)行了。
 
1.3.3   互斥量獨有的特性(另參附錄的實驗)
互斥量對象與所有其它內核對象的不同之處在于它是被線程所擁有的。其它所有同步對象要么有信號,要么無信號,僅此而已。而互斥量對象除了記錄當前信號狀態(tài)外,還要記住此時那個線程擁有它。如果一個線程在得到一個互斥量對象(即將其置為無信號態(tài))后就終結了,互斥量也就廢棄了。在這種情況了,互斥量將永遠保持無信號態(tài),因為沒有其它線程能夠通過調用ReleaseMutex來釋放它。
系統(tǒng)發(fā)現(xiàn)產生這種情況時,就自動將互斥量設回有信號狀態(tài)。其它等待該信號量的線程就會被喚醒,但函數(shù)的返回值為WAIT_ABANDONED而不是正常的WAIT_OBJECT_0。這時,其它線程可以知道互斥量是不是被正常釋放。
其它的,互斥量與CRITICAL_SECTION類似。擁有該互斥量的線程,每次調用WaitForSingleObject都會立即成功返回,但互斥量的使用計數(shù)將增加,同樣的,也要多次調用ReleaseMutex以使引用計數(shù)變?yōu)榱?,方可供別的線程使用。
1.3.3.1             疑問
 
問:其它內核對象在線程異常終止沒有釋放所有權時,系統(tǒng)回重置其狀態(tài)嗎?如果重置,將沒有任何標記,與正常釋放無異,即不會擁有互斥量的這個返回WAIT_ABANDONED的特性?
 
【注意:線程擁有某個內核對象線程擁有某個內核對象的所有權,這二者是不同的。當說線程擁有某個內核對象時,要強調的是當該線程終止時,若線程正好擁有該內核對象的訪問權,內核對象也將被廢棄―――因為不能重置其信號狀態(tài);而線程擁有某一個內核對象的所用權,指的是線程可以調用某些函數(shù),訪問該內核對象或對該內核對象執(zhí)行某些操作】
答:見附錄中后面的“討論與實驗一”。
1.3.4   WaitForSingleObject與WaitForMultipleObjects
線程主要使用兩個函數(shù)將它們設為睡眠來等待內核對象變?yōu)?strong>有信號:即都是阻塞函數(shù)。
DWORD WaitForSingleObject(
 HANDLE hHandle,
 DWORD dwMilliseconds
);
 
DWORD WaitForMultipleObjects(
 DWORD nCount,
 const HANDLE* lpHandles,
 BOOL bWaitAll,
 DWORD dwMilliseconds
);
 
WaitForSingleObject,在一個指定時間(dwMilliseconds)內等待某一個內核對象變?yōu)橛行盘?,在此時間內,若等待的內核對象一直是無信號的,則調用線程將睡眠,否則繼續(xù)執(zhí)行。超過此時間后,線程繼續(xù)運行。函數(shù)返回值可能為:WAIT_OBJECT_0、WAIT_TIMEOUT、WAIT_ABANDONED(僅當內核對象為互斥量時)、WAIT_FAILED。
WaitForMultipleObjects與WaitForSingleObject類似,只是它要么等待指定列表(由lpHandles指定)中若干個對象(由nCount決定)都變?yōu)橛行盘?,要么等待一個列表(由lpHandles指定)中的某一個對象變?yōu)橛行盘枺ㄓ蒪WaitAll決定)。
 
WaitForSingleObject和WaitForMultipleObjects函數(shù)對特定的內核對象有重要的副作用―――即它們根據(jù)不同的內核對象,會決定是否改變內核對象的信號狀態(tài),并執(zhí)行這種改變;這些副作用,決定了是讓等待該內核對象的進程或線程中的某一個被喚醒還是全都被喚醒。
1、 對進程和線程內核對象,這兩個函數(shù)不產生副作用。即,在進程或線程內核對象變?yōu)橛行盘柡螅鼈儗⒈3钟行盘?,這兩個函數(shù)不會試圖改變內核對象的信號狀態(tài)。這樣,所有等待這些內核對象的線程都會被喚醒。
The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters the wait state. It uses no processor time while waiting for the object state to become signaled or the time-out interval to elapse.
The function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.
2、 對于互斥量、自動重置事件和自動重置可等的計時器對象,這兩個函數(shù)將把它們的狀態(tài)改為無信號。換言之,一旦這些對象變?yōu)橛行盘柌⑶矣幸粋€線程被喚醒,則對象重被置為無信號狀態(tài)。于是,只有一個正在等待的線程醒來,其它等待的線程將繼續(xù)睡眠。
3、 對于WaitForMultipleObjects函數(shù)還有非常重要的一個特性:當調用它時傳遞的bWaitAll為TRUE時,在所有被等待的對象都變?yōu)橛行盘栔?,被等待的任何可以被改變狀態(tài)的內核對象都不被重置為無信號狀態(tài)。換言之,在傳入參數(shù)bWaitAll為TRUE,WaitForMultipleObjects除非能取得所有指定對象(由lpHandles指定)的所有權,它不會取得單個對象的所有權(不能取得所有權,自然也不會改變此對象的信號狀態(tài))。這是為了防止死鎖。換言之,在bWaitAll為TRUE時,WaitForMultipleObjects不會在沒有獲得所有被等對象所有權的情形下改變某一可以被改變狀態(tài)的內核對象的信號狀態(tài),任何以同樣方式等待的線程都不會被喚醒―――但以其它方式等待的線程將被喚醒。
The WaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state. It uses no processor time while waiting for the criteria to be met.
When bWaitAll is TRUE, the function's wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled. For example, a mutex can be signaled, but the thread does not get ownership until the states of the other objects are also set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting its state to nonsignaled.
The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When bWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait(
到底選擇哪一個呢?天知道!); the states of the objects not selected are unaffected.
1.3.5   事件或定時器的自動重置與手動重置
1.         自動重置:在內核對象變?yōu)橛行盘枙r,僅有一個線程可以獲得它,該線程一旦獲得,內核對象又將變?yōu)闊o信號態(tài),其它等待的線程將繼續(xù)睡眠。由Wait類函數(shù)實現(xiàn)自動重置未無信號狀態(tài)的功能。
2.         手動重置:一般來說,所有等待該信號的線程都會蘇醒過來。在你調用相關函數(shù)將內核對象置為無信號狀態(tài)前,內核對象將一直處于信號狀態(tài)。
2       附錄
2.1    討論與實驗一:內核對象處于非信號狀態(tài)時,相關線程結束時內核對象是否被系統(tǒng)重置為信號臺?
互斥量被某一線程擁有,若線程退出但未釋放相應互斥量,操作系統(tǒng)將調用ReleaseMutex釋放相應互斥量。對于信號量和事件呢?若沒有被正確釋放或重置,操作系統(tǒng)是否在進程結束后嘗試像對互斥量進行釋放的操作?――若不,那么,對沒有正確釋放的信號量和事件,在操作系統(tǒng)的本次運行期間將一直存在,是么?:舉例來說,若進程使用某一事件來完成唯一實例,若進程退出后沒有正確釋放相應事件,那么,在系統(tǒng)重新啟動之前,進程將不能運行。是么?
 
注意,對于內核對象來說,若其引用計數(shù)變?yōu)?,系統(tǒng)將銷毀該內核對象。為了比較,我以Event和Mutex分別構造幾個應用程序。(注意,Mutex是屬于線程的,但這里的應用程序都是單線程的,換言之,這里沒有測試到進程內某一擁有互斥量的線程不釋放互斥量便退出的情況?。?/div>
 
2.1.1   Event程序
使用Event的應用程序有四。Event創(chuàng)建時置為手動重置事件,初始狀態(tài)為有信號狀態(tài),換言之,以::CreateEvent(NULL, TRUE, TRUE, "KernelObjectsEvent ")方式創(chuàng)建。還有,以WaitForSingleObject(內核對象句柄,0)方式等待“KernelObjectsEvent”名的Event對象。
1.         Event_OnlyReferences~僅僅嘗試用CreateEvent獲取Event句柄,不等待該Event,也不改變它的任何狀態(tài)。
2.         Event_AfterWaitnonSignaled~同樣方式調用CreateEvent,然后等待,成功后置為無信號態(tài)。應用程序繼續(xù)運行。
3.         Event_setEventBeforeWaitAfternonSignaled~同樣方式調用CreateEvent,但在等待前置事件為信號臺,然后等待,成功后置為信號態(tài)。
4.         Event_setEventBeforeWaitAfterSignaled~同樣方式調用CreateEvent,但在等待前置事件為信號臺,然后等待,成功后置為信號態(tài)。
 
2.1.2   Mutex程序
使用Mutex的應用程序有四。Mutex創(chuàng)建時置為非進程擁有,換言之,以CreateMutex(NULL, FALSE, "KernelObjectsMutex")方式創(chuàng)建。還有,以WaitForSingleObject(內核對象句柄,0)方式等待“KernelObjectsMutex”名的Mutex對象
1.         Mutex_OnlyReferences~僅僅嘗試用CreateMutex獲取Mutex句柄,不等待該Mutex,也不會嘗試釋放它。
2.         Mutex_AfternonSignaled~同樣方式調用CreateMutex,然后等待,成功后并不嘗試釋放它。應用程序繼續(xù)運行。
3.         Mutex_ReleaseBeforeWaitAfternonSignaled~同樣方式調用CreateMutex,但在等待前嘗試多次調用ReleaseMutex釋放它,然后等待,成功后并不嘗試釋放它。
4.         Mutex_ReleaseBeforeWaitAfterSignaled~同樣方式調用CreateMutex,但在等待前嘗試多次調用ReleaseMutex釋放它,然后等待,成功后置再次釋放它。
2.1.3   實驗一
2.1.3.1             Event
1.         Event_OnlyReferences……運行成功,別終止程序。
2.         第一次運行Event_AfterWaitnonSignaled……運行成功,別終止程序。
3.         第二次運行Event_AfterWaitnonSignaled……運行不成功,程序退出。
4.         Event_setEventBeforeWaitAfternonSignaled……運行成功,別終止程序。
5.         第三次運行Event_AfterWaitnonSignaled……運行不成功,程序退出。
6.         Event_setEventBeforeWaitAfterSignaled……運行成功,別終止程序。
7.         第四次運行Event_AfterWaitnonSignaled……運行成功,別終止程序。
2.1.3.2             Mutex
1.         Mutex_OnlyReferences……運行成功,別終止程序。
2.         第一次運行Mutex_AfternonSignaled……運行成功,別終止程序。
3.         第二次運行Mutex_AfternonSignaled……運行不成功,程序退出。
4.         Mutex_ReleaseBeforeWaitAfternonSignaled……運行不成功,程序退出。
5.         第三次運行Mutex_AfternonSignaled……運行不成功,程序退出。
6.         Mutex_ReleaseBeforeWaitAfterSignaled……運行不成功,程序退出。
7.         第三次運行Mutex_AfternonSignaled……運行不成功,程序退出。
2.1.3.3             結論
1.         只有當前擁有Mutex的線程調用ReleaseMutex函數(shù)才會返回TRUE,并且才會釋放該Mutex;不擁有該Mutex的線程調用ReleaseMutex函數(shù)就是簡單的返回FALSE。
2.         而Mutex并不屬于某一個線程擁有,它屬于操作系統(tǒng),不關當前事件是有信號還是無信號,你都能調用SetEvent或ResetEvent改變其狀態(tài)。―――換言之,如果你在你的應用程序中任意一處沒有正確的按照規(guī)則調用SetEvent或ResetEvent,你將達不到同步或互斥的目的。
3.         【注意:一般來說,都是利Event來進行同步,而不是我們這里的讓它來達到互斥;而作為互斥與線程無關的內核對象應該是Semaphore;而作為互斥與線程有關的內核對象應該是Mutex?!?/div>
 
2.1.4   實驗二
 
2.1.4.1             Event
1.         運行Event_OnlyReferences……運行成功,別終止程序。
2.         第一次運行Event_AfterWaitnonSignaled……運行成功,別終止程序。
3.         運行Event_setEventBeforeWaitAfternonSignaled……運行成功,別終止程序。
4.         除了第一次運行的Mutex_OnlyReferences外,關閉所有其它應用程序。
5.         第二次運行Event_AfterWaitnonSignaled……運行不成功,程序退出。
6.         運行Event_setEventBeforeWaitAfterSignaled……運行成功,別終止程序。
7.         除了第一運行的Event_OnlyReferences外,關閉所有其它程序。
8.         第三次運行Event_AfterWaitnonSignaled程序……運行成功,別終止程序。
 
2.1.4.2             Mutex
1.         運行Mutex_OnlyReferences……運行成功,別終止程序。
2.         第一次運行Mutex_AfternonSignaled……運行成功,別終止程序。
3.         運行Mutex_ReleaseBeforeWaitAfternonSignaled……運行不成功,程序退出。
4.         除了第一次運行的Mutex_OnlyReferences外,關閉所有其它應用程序。
5.         第二次運行Mutex_AfternonSignaled……捕捉到WAIT_ABANDONED信號,這里我們讓程序繼續(xù)運行。別中止程序。
6.         運行Mutex_ReleaseBeforeWaitAfterSignaled……運行不成功,程序退出。
7.         除了第一次運行的Mutex_OnlyReferences外,關閉所有其它應用程序。
8.         第三次運行Mutex_AfternonSignaled……運行成功,別終止程序。
 
2.1.4.3             結論
1.         Event處于無信號狀態(tài)時,相關線程或進程退出,系統(tǒng)并不會嘗試為你將其置為有信號狀態(tài)―――所以Event實驗中第5步運行不成功。但由于它(這里的它是內核對象,而不是內核對象的句柄)不屬于任何進程或線程,你可以再任何別的程序中重新將它置為信號臺,所以第6步執(zhí)行成功。
2.         Mutex處于無信號狀態(tài)時,當前擁有它的線程或進程退出,系統(tǒng)會嘗試將其置為有信號狀態(tài)―――所以Mutex實驗中第5步運行成功,但捕捉到WAIT_ABANDONED信號,它指明是操作系統(tǒng)為你重置為有信號狀態(tài)的。同樣,由于某一線程現(xiàn)在擁有它,它未釋放該互斥量且線程未退出時,它屬于這個線程,你不能剝奪它的權利,所以第6步運行不成功。
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服