1. 程式人生 > >執行緒和同步

執行緒和同步

執行緒和同步

1. 多執行緒作用


提高應用程式響應。利用多執行緒程式設計並不一定能加快程式執行的速度,其目的是擁有更加良好的程式響應。例如在一個圖形介面執行一個操作的同時啟動另一個。
使多CPU系統更加有效。
改善程式結構。多執行緒程式比單執行緒程式更能適應使用者需求的變更。
佔用更小的系統資源。執行緒的資料結構簡單,停止、執行速度快,程序是執行緒的靠山,是車間,執行緒是小組,活動方便。程序任務大、資訊多,將它細分為執行緒後,各執行緒可共享程序分到的資源,排程方便。

2. 執行緒和同步

使用多程序於多執行緒時,有時需要協同兩種或多種動作,此過程就稱為同步(Synchronization)


2.1 等待函式


  Win32 API 提供了一組能使執行緒阻塞其自身的等待函式。這些函式在其引數中的一個或多個同步物件產生了訊號,或者超過規定的等待時間才會返回。在等待函式未返回時,執行緒處於等待狀態,此時執行緒只消耗很少的CPU時間。使用等待函式即可以保證執行緒的同步,又可以提高程式的執行效率。

 

 

DWORD WINAPI WaitForSingleObject(
  _In_ HANDLE hHandle,
  _In_ DWORD  dwMilliseconds
);//檢測一個同步物件1234

 

DWORD WINAPI WaitForMultipleObjects(
  _In_       DWORD  nCount,
  _In_ const HANDLE *lpHandles,
  _In_       BOOL   bWaitAll,
  _In_       DWORD  dwMilliseconds
);//檢測多個同步物件123456


2.2 互斥體物件 - 互斥量 

Mutux物件的狀態在它不被任何執行緒擁有時才有訊號,而當它被執行緒擁有時則無訊號

Mutex物件很適合用來協調多個執行緒對共享資源的互斥訪問

可以按下列步驟使用該物件:

建立互斥體物件,得到控制代碼

HANDLE CreateMutex();1
線上程可能產生衝突的區域前(即訪問共享資源之前)呼叫WaitForSingleObject,將控制代碼傳給函式,請求佔用互斥物件

dwWaitResult = WaitForSingleObject(hMutex, 5000);1
共享資源訪問結束,釋放對互斥體物件的佔用

ReleaseMutex(hMutex);1

互斥體物件在同一時刻只能被一個執行緒佔用,當互斥體物件被一個執行緒佔用時,若有另一個執行緒想佔用它,則必須等到前一執行緒釋放後才能成功。


2.3 訊號物件--訊號量

訊號物件允許同時對多個執行緒共享資源進行訪問,在建立物件時指定最大可同時訪問的執行緒數。當一個執行緒申請訪問成功後,訊號物件中的計數器減1,呼叫ReleaseSemaphore函式後,訊號物件中的計數器加1。其中,計數器值大於或等於0,單小於或等於建立時指定的最大值。如果一個應用在建立一個訊號物件時將其計數器的初始值設為0,則阻塞了其他執行緒,保護了資源。等初始化完成後,呼叫ReleaseSemaphore函式將其計數器增加至最大值,則可進行正常的存取訪問。

可以按下列步驟使用該物件:

建立訊號物件或開啟一個訊號物件

HANDLE CreateSemaphore();
//或者開啟一個物件
HANDLE OpenSemaphore();123
線上程訪問共享資源之前呼叫WaitForSingleObject。
在共享資源訪問完成後,應釋放對訊號物件的佔用

ReleaseSemaphore();1


2.4 事件物件

事件物件(Event)是最簡單的同步物件,它包括有訊號和無訊號兩種狀態。線上程訪問某一資源之前,需要等待某一事件的發生,這是用事件物件最合適。例如:只有在通訊埠緩衝區收到資料後,監視執行緒才被啟用。

事件物件是用CreateEvent函式建立的。該函式可以指定事件物件的類和事件的初始狀態。如果是手工重置事件,那麼它總是保持有訊號狀態,直到用ResetEvent函式重置成無訊號事件。如果是自動重置事件,那麼它的狀態在單個等待執行緒釋放後會自動變為無訊號的。用SetEvent可以把事件物件設定成有訊號狀態。在建立事件時,可以為物件命名,這樣其他程序中的執行緒可以用OpenEvent函式開啟指定名字的事件物件控制代碼


2.5 排斥區物件

在排斥區中非同步執行時,它只能在同一程序的執行緒之間共享資源處理 。雖然此時上面介紹的幾種方法均可使用,但是,使用排斥區的方法則使同步管理的效率更高。

使用時先定義一個CRITICAL_SECTION結構的排斥區物件,在程序使用之前呼叫如下函式對物件進行初始化:

VOID InitializeCriticalSection(LPCRITICAL_SECTION)1

當一個執行緒使用排斥區時,呼叫函式EnterCriticalSection或TryEnterCriticalSection。

當要求佔用、退出排斥區時,呼叫函式LeaveCriticalSection釋放對排斥區物件的佔用,供其他執行緒使用


--------------------- 
作者:zt_xcyk 
來源:CSDN 
原文:https://blog.csdn.net/zt_xcyk/article/details/72959278 
版權宣告:本文為博主原創文章,轉載請附上博文連結!