VC 執行緒同步

2021-06-09 04:54:28 字數 4018 閱讀 7512

2008-09-02 10:47:02

|  分類:

vc程式設計

|  標籤:|字型大小

大中小訂閱

什麼是同步:

「同步」不是指平常所說的兩件事情同時進行。它的目的是使多個執行緒之間協調工作,而且常常是避免兩個執行緒同時進行某些操作,比如同時訪問同乙個共享資源。一般來說,同步是通過暫時將會發生衝突操作的某個執行緒暫停執行(稱為阻塞執行緒),然後等待不會衝突時再繼續執行。

需要同步的情況:

1、多個執行緒同時訪問同一物件時

mfc物件在物件級不是執行緒安全的,只有在類級才是。如:兩個執行緒可以安全地使用兩個不同的cstring物件,但同時使用同乙個cstring物件就可能產生問題。如果必須使用同乙個物件,那麼應該採取適當的同步化措施。

2、多個執行緒之間需要協調執行

例如,如果第二個執行緒需要等待第乙個執行緒完成到某一步時才能執行,那麼該執行緒應該暫時掛起以減少對cpu的占用時間,提高程式的執行效率。當第乙個執行緒完成了相應的步驟後,應該發出某種訊號來啟用第二個執行緒。

windows中的4種執行緒同步物件:

1、events(事件)——cevent

2、critical sections(臨界段)——ccriticalsection

在程序中作為關鍵字以獲得對共享資源的訪問

3、mutexes(互斥量)——cmutex

與臨界段的工作方式相似,只是該物件可以用於多程序中的執行緒同步,而不是用於單程序中

4、semaphores(訊號量)——csemaphore

在給定的限制條件下,允許多個程序同時訪問共享資源

注意:使用執行緒同步類,必須在檔案中包含afxmt.h標頭檔案。執行緒同步類的基類是csyncobject。

事件:

cevent類的建構函式,第乙個引數確定事件物件的起始訊號狀態,true代表活動(有訊號)狀態,false代表沉寂(無訊號)狀態。預設情況下,是自動事件。

第二個引數為false,是自動事件,自動事件在呼叫setevent函式被使用後能夠自動恢復為無訊號狀態;第二個引數為true,是手動事件,手動事件在呼叫setevent函式處於活動狀態時,一直出於這個狀態,直到程式顯式地呼叫resetevent為止。所以,cevent::resetevent函式只用於手動事件。

自動事件:

cevent類的建構函式,第二個引數為false,是自動事件,自動事件在呼叫setevent函式被使用後能夠自動恢復為無訊號狀態。預設情況下,是自動事件。

1、宣告事件為全域性物件。

//包含使用執行緒同步物件所需要的標頭檔案

#include "afxmt.h"

cevent eventobj; //構造乙個自動事件物件

2、在乙個執行緒中使用csyncobject::lock函式來等待訊號,如果事件無訊號,該執行緒被掛起等待。

//鎖住事件

eventobj.lock(); //等待事件有訊號才返回

3、在另外乙個執行緒中使用cevent::setevent來設定適當的事件為有訊號狀態,此時即可讓等待的執行緒繼續執行。

eventobj.setevent(); //設定事件變成有訊號狀態

注意:一般來說,在實際應用中不要輕易阻塞主線程,因為主線程一般是負責和使用者進行互動的,阻塞主線程會影響應用程式的互動性。

手動事件:

cevent類的建構函式,第二個引數為true,是手動事件,手動事件在呼叫setevent函式處於活動狀態時,一直出於這個狀態,直到程式顯式地呼叫resetevent為止。

為了簡便起見,後面所有執行緒函式都通過彈出訊息框的形式來告知使用者執行緒的同步情況。同時約定,在檢視區單擊滑鼠左鍵就會建立乙個工作執行緒。單擊滑鼠右鍵則使事件物件處於有訊號狀態。

自動事件就好比地鐵的自動檢票口,一張票(setevent)只能使乙個人(執行緒)通過;而手動事件則可以理解為路口的紅綠燈,紅燈表示無訊號,所有的人(執行緒)都必須等待,當變為綠燈時(事件有訊號),所有等待的人都可以通過,直到下次變為紅燈(呼叫resetevent函式)為止。

臨界段:

臨界段(critical sections)是一種保證在某一時刻只有乙個執行緒能夠訪問共享資料的簡便方法,只能被使用在乙個程序內的執行緒間進行通訊。

1、宣告臨界段為全域性物件。

//包含使用執行緒同步物件所需要的標頭檔案

#include "afxmt.h"

ccriticalsection criticalsection; //構造乙個自動事件物件

2、執行緒想訪問共享資源,會呼叫臨界段的成員函式,該函式會將資源關鍵字交給呼叫執行緒(假設其他執行緒沒有擁有該臨界段):

criticalsection.lock(); //試圖鎖定臨界段

如果其他執行緒已經鎖定了該臨界段,那麼呼叫執行緒都會處於阻塞狀態,直到該臨界段被釋放為止。否則,呼叫執行緒就會成為該臨界段的擁有者,並且能夠訪問共享資源。

3、呼叫執行緒完成對資源的處理後,通過呼叫下面的函式來釋放臨界段物件:

criticalsection.unlock(); //解除臨界段

釋放的臨界段物件就可以被其他執行緒物件得到,並訪問受保護的資料。

多個執行緒使用臨界段訪問共享資源就好比人們在火車上去洗手間。每個人代表乙個執行緒,因此,洗手間的門鎖就是臨界段物件了。每個執行緒(人)使用共享資源時(洗手間),必須先使用臨界段物件(門鎖)鎖住共享資源。如果共享資源已經被其他執行緒鎖住了,則必須等待,直到臨界段物件(門鎖)被釋放為止。

互斥量:

互斥量(mutexes)的作用和臨界段幾乎相同,也用於保證在某一時刻只有乙個執行緒能夠訪問共享資料,但可以用作不同程序內的執行緒間通訊。不僅能夠在同乙個應用程式的執行緒之間實線資源的安全共享,而且可以在不同應用程式的執行緒之間實線安全的資源共享。

1、在應用程式中建立乙個全域性互斥量物件:

//包含使用執行緒同步物件所需要的標頭檔案

#include "afxmt.h"

cmutex mutex(false, "mutex1"); //宣告乙個名為mutex1的互斥量物件

注意:如果互斥量要被使用在不同應用程式的程序通訊,則必須指定乙個名字。第乙個引數設定互斥量的開始狀態是鎖定(true)還是未鎖定(false)。第二個引數指向互斥量的名稱,該名稱用於區別系統中不同程序定義的互斥量。

2、在程式即將訪問共享資源士,呼叫物件的lock成員函式鎖定:

mutex.lock(); //鎖定互斥量

3、程式完成了對共享資源的使用後,呼叫互斥量的unlock成員函式釋放:

mutex.unlock(); //釋放互斥量

訊號量:

訊號量(semaphores)的作用是允許一定數目的執行緒同時訪問某個共享資源,也可以用作不同程序內的執行緒間通訊。訊號量維護著乙個從0開始的計數,在計數值大於0時物件是有訊號的,而在計數值為0時則是無訊號的。每當有乙個新的執行緒奪得了資源,計數值就減少;而當某執行緒釋放了資源,計數值增加。當計數值為0時,除非有乙個執行緒釋放該資源,否則其他執行緒無法訪問該資源。

1、建立乙個全域性的訊號量物件,並設定初始資源數和最大資源數。如果要在程序間使用訊號量,那麼還要設定訊號量名:

//包含使用執行緒同步物件所需要的標頭檔案

#include "afxmt.h"

csemaphore semaphore(2, 2, "semaphore1"); //宣告乙個名為semaphore1的訊號量

semaphore.lock(); //訊號量可用資源減1

semaphore.unlock(); //訊號量可用資源加1

訊號量的例子,如汽車進加油站,每輛汽車就是乙個執行緒,而加油站就是共享資源。但這個加油站只有4個加油點(相當於訊號量的計數值),也就是說同時只能有4輛車在加油。如果還有更多的車想加油,就必須排隊等候了。

VC多執行緒的同步

1.利用事件物件同步 事件分為 人工重置的事件物件和自動重置的事件物件。人工重置的事件物件 收到通知,等待的所以執行緒變為可排程執行緒。自動重置的事件物件 收到通知,等待的所以執行緒只有乙個變為可排程。同時作業系統會將事件物件設定為無訊號狀態。為了實現執行緒間的同步,不應該使用人工重置的事件物件,而...

VC 中線程同步技術分析4

管理事件核心物件 在前面講述執行緒通訊時曾使用過事件核心物件來進行執行緒間的通訊,除此之外,事件核心物件也可以通過通知操作的方式來保持執行緒的同步。對於前面那段使用臨界區保持執行緒同步的 可用事件物件的執行緒同步方法改寫如下 事件控制代碼 handle hevent null 共享資源 char g...

VC 多執行緒同步方式操作串列埠

include includeusing namespace std dword winapi commreceive lpvoid lpparameter dword winapi commsend lpvoid lpparameter handle m hcom int main 設定緩衝區大小...