1. 程式人生 > >[作業系統]Windows環境下的多執行緒臨界資源訪問

[作業系統]Windows環境下的多執行緒臨界資源訪問

目錄

                    SetEvent/ResetEvent 

                    ReleaseMutex

DWORD WaitForSingleObject( HANDLE THandle, DWORD Timeout)

作用:使執行緒處於等待狀態,如等待某一事件的觸發。用最簡單的語言說就是這個物件有兩個狀態比如我們稱0和1,稱什麼一點也不重要,有訊號和無訊號就是相對的兩個狀態,沒什麼意義,你就認為一個狀態是0另一個狀態是1。
在程式裡如果加了WaitForSingleObject,那麼程式到這裡就去檢測你給他的那個控制代碼的狀態,如果是0程式就停在這裡了,如果是1,程式就繼續下去。
那麼

執行緒同步就要利用這兩個狀態。假如你有兩個執行緒,都有可能訪問同一個檔案,而同一個檔案是不能被兩個執行緒同時寫入的,那麼你就需要在寫入之前先判斷檔案有沒有被另一個執行緒在寫入,如果有則等著,等另一個執行緒寫完之後你再繼續,我們不能用一個死循壞來嘗試開啟檔案知道成功為止,這樣會讓CPU有非常高的佔用率。
這裡你就要建立一個物件,這個物件有兩個狀態,我們約定,如果一個執行緒要寫入檔案之前就把這個物件狀態變成0,寫完之後把它變回1,那麼另一個執行緒在寫檔案之前只要檢測這個物件是不是為0就可以確定檔案有沒有被另一個執行緒在寫入了。檢測的過程就用WaitForSingleObject來操作,如果為1,WaitForSingleObject就和沒這句話一樣立刻執行下去了,如果那個物件是個0,那麼WaitForSingleObject就會停在這裡等,等到另一個執行緒寫完檔案,因為那個執行緒在寫完檔案之後會把物件變成1。
這個狀態1我們命名為有訊號狀態,狀態0我們稱無訊號狀態。我們就把這個物件叫做互斥體,他起到了對這個檔案讀寫的互斥作用。這整個寫檔案之前之後改變互斥體狀態,寫之前檢測互斥體狀態這個過程就是一個執行緒的同步。
同步是程式設計的人自己要考慮的問題,系統不會幫你同步,也就是說我們進行了上述的約定之後,你在程式設計的時候必須要在寫入檔案之前將互斥體置為無訊號狀態,寫完之後置為有訊號狀態

THandle:等待觸發的控制代碼

Timeout:等待多長時間,單位ms。想無限等待下去,Timeout引數可以指定系統常量INFINITE。

返回值:WAIT_ABANDONED:指定的物件是一個互斥物件,該物件沒有被擁有該物件的執行緒線上程結束前釋放。互斥物件的所                                                          有權被同意授予呼叫該函式的執行緒。互斥物件被設定成為無訊號狀態。當THandle為mutex時,如                                                           果擁有mutex的執行緒在結束時沒有釋放核心物件會引發此返回值。

                                                          表示物件有訊號,但還是不能執行 ,一般是因為未獲取到鎖或其他原因

          WAIT_OBJECT_0:核心物件已被啟用,對執行緒來說,表示執行結束

          WAIT_TIMEOUT:等待超時,表示等待指定時間內,物件一直沒有訊號,即執行緒沒執行完

          WAIT_FAILED:出現錯誤,可通過GetLastError得到錯誤程式碼

HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName )

LPSECURITY_ATTRIBUTES lpMutexAttributes: 指向安全屬性的指標

BOOL bInitialOwner:初始化互斥物件的所有者 。

                                      如果為TRUE,呼叫互斥物件的執行緒獲得互斥物件的所有權  如果為FALSE,則不擁有

                                     true:人工重置事件物件,等待該事件的所有程序都將進入執行
                                     false:自動重置事件物件,等待該事件中的一個程序可變為排程。表示剛剛建立的這個Mutex                                                                   不屬於任何執行緒,也就是沒有任何執行緒擁有他,一個Mutex在沒有任何執行緒擁有他的時                                                                             候,他是處於激發態的, 所以處於有訊號狀態。
LPCTSTR lpName :指向互斥物件名的指標。

                                      如果lpName跟一個已存在的事件、訊號、檔案對映物件匹配,即命名的互斥物件已存在,

                                     則CreateMutex函式失敗,
                                     true: 建立該事件物件後,觸發事件

                                     false:不觸發事件。

HANDLE CreateThread(LPSECURITY_ATTRIBUTES secAttr, SIZE_T  stackSize,LPTHREAD_START_ROUTINE  threadFunc,    
LPVOID    param,DWORD  flags,   LPDWORD  threadID)

secAttr:描述執行緒核心物件安全屬性的指標,設定為NULL,就會使用預設的安全描述符。

stackSize:表示執行緒棧空間大小。如果為0(1MB),那麼這個執行緒堆疊的大小與建立它的執行緒相同。

threadFunc:表示新執行緒所執行的執行緒函式地址,多個執行緒可以使用同一個函式地址,執行緒的執行一直持續到執行緒函式返回。

param:傳給執行緒函式的引數。

flags:標誌了執行緒的執行狀態,為0表示執行緒建立之後立即就可以進行排程,如果為CREATE_SUSPENDED,
            執行緒則以掛起狀態建立並等待執行,這樣它就無法排程,直到呼叫ResumeThread()。

threadID:將以的長整型返回執行緒的ID號,傳入NULL表示不需要返回該執行緒ID號。

BOOL  TerminateThread(HANDLE   hThread, DWORD   dwExitCode)

hThread :欲令其結束執行緒的handle,該執行緒就是我們的行動目標。

dwExitCode: 該執行緒的結束程式碼。

SetEvent/ResetEvent(EVENT)

EVENT有兩種狀態:發訊號,不發訊號。

SetEvent/ResetEvent分別將EVENT置為這兩種狀態分別是發訊號與不發訊號。 

BOOL WINAPI  ReleaseMutex(HANDLE hMutex)

作用:釋放互斥物件的控制權。一個執行緒釋放了互斥物件的控制權後,如果其他程序在等待互斥物件置位,則等待的執行緒可以得到該互斥物件,等待函式返回,互斥物件被新的執行緒所擁有。
返回值:TRUE表示成功,FALSE表示失敗。
hMutex:HANDLE,制定一個互斥體的控制代碼。