C++ 线程同步之临界区CRITICAL_SECTION
一、臨界區臨界區又稱關鍵代碼段,指的是一小段代碼在代碼執行前,他需要獨占一些資源。程序中通常將多線程同時訪問的某個資源作為臨界區,需要定義一個CRITICAL_SECTION類型的變量,然后調用InitializeCriticalSection函數對變量進行初始化;函數聲明:VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection );lpCriticalSection:一個CRITICAL_SECTION結構指針,表示用于初始化的臨界區;InitializeCriticalSection函數在內部設置了CRITICAL_SECTION結構的某些成員變量,所以他不會失敗。為了將某一段代碼定義為臨界區,需要調用EnterCriticalSection函數;VOID WINAPI EnterCriticalSection(__inout LPCRITICAL_SECTION lpCriticalSection);該函數的作用是判斷是否有線程訪問臨界區資源,如果沒有,就改變CRITICAL_SECTION結構的成員變量的值,賦予當前線程訪問權,函數立即返回;如果有線程正在訪問資源,則進入等待狀態,直到沒有線程訪問。釋放資源函數:void WINAPI LeaveCriticalSection( _Inout_LPCRITICAL_SECTION lpCriticalSection);釋放CRITICAL_SECTION結構指針void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);二、學習案例用三個線程同時運行將一個變量增加到30;臨界區對象類#ifndef CAUTO_LOCK_H__#define CAUTO_LOCK_H__ class CAutoLock{public:?? ?CAutoLock();?? ?~CAutoLock(); ?? ?void Lock();?? ?void UnLock(); private:?? ?CRITICAL_SECTION m_Section;}; #endif#include "stdafx.h"#include "CAutoLock.h" CAutoLock::CAutoLock(){?? ?InitializeCriticalSection(&m_Section);?? ?//Lock();如果是用的時候只定義鎖對象,可以不手動進入臨界區和退出臨界區} CAutoLock::~CAutoLock(){?? ?DeleteCriticalSection(&m_Section);?? ?//UnLock();} void CAutoLock::Lock(){?? ?EnterCriticalSection(&m_Section);} void CAutoLock::UnLock(){?? ?LeaveCriticalSection(&m_Section);}三個線程創建類#ifndef _TEST_CRITICAL_SECTION_H__#define _TEST_CRITICAL_SECTION_H__#include "CAutoLock.h"class TestCriticalSection{public:?? ?TestCriticalSection();?? ?~TestCriticalSection(); ?? ?void StartThread();//開始線程函數 ?? ??? ?static DWORD __stdcall ThreadFun1(LPVOID lParam);//線程回調函數1?? ?static DWORD __stdcall ThreadFun2(LPVOID lParam);//線程回調函數2?? ?static DWORD __stdcall ThreadFun3(LPVOID lParam);//線程回調函數3 private:?? ?HANDLE m_hThread1; ? ? ? ?HANDLE m_hThread2;?? ?HANDLE m_hThread3; ?? ?CAutoLock m_lock;//三個線程公用的臨界區鎖 ?? ?static int m_nTotals;}; #endif#include "stdafx.h"#include "CCriticalSection.h"#include <iostream>using namespace std; int TestCriticalSection::m_nTotals = 0;//初始化靜態成員變量 TestCriticalSection::TestCriticalSection(){?? ?m_nTotals = 0; ? ? ? ?m_hThread1 = INVALID_HANDLE_VALUE;?? ?m_hThread2 = INVALID_HANDLE_VALUE;} TestCriticalSection::~TestCriticalSection(){?? ?if (m_hThread1 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread1);?? ??? ?m_hThread1 = NULL;?? ?} ?? ?if (m_hThread2 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread2);?? ??? ?m_hThread2 = NULL;?? ?} ?? ?if (m_hThread3 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread3);?? ??? ?m_hThread3 = NULL;?? ?}} DWORD __stdcall TestCriticalSection::ThreadFun1(LPVOID lParam) //static只需要加在類定義里,類定義外面的函數定義前不能寫static{?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun1: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?} ?? ?return dRet;} DWORD __stdcall TestCriticalSection::ThreadFun2(LPVOID lParam){?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun2: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?}?? ?return dRet;} DWORD __stdcall TestCriticalSection::ThreadFun3(LPVOID lParam){?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun3: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?} ?? ?return dRet;} void TestCriticalSection::StartThread(){?? ?m_hThread1 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun1, this, ?0, NULL);?? ?m_hThread2 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun2, this, 0, NULL);?? ?m_hThread3 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun3, this, 0, NULL);}主函數:// CriticalSection.cpp : 定義控制臺應用程序的入口點。// #include "stdafx.h"#include "CCriticalSection.h" int _tmain(int argc, _TCHAR* argv[]){?? ?TestCriticalSection ?CriticalSectionObj;?? ?CriticalSectionObj.StartThread();?? ?Sleep(5000);?? ?system("pause");?? ?return 0;} 結果:如果代碼改成下面這樣,不加臨界區;資源訪問會沖突#include "stdafx.h"#include "CCriticalSection.h"#include <iostream>using namespace std; int TestCriticalSection::m_nTotals = 0; TestCriticalSection::TestCriticalSection(){?? ?m_nTotals = 0; ? ?m_hThread1 = INVALID_HANDLE_VALUE;?? ?m_hThread2 = INVALID_HANDLE_VALUE;} TestCriticalSection::~TestCriticalSection(){?? ?if (m_hThread1 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread1);?? ??? ?m_hThread1 = NULL;?? ?} ?? ?if (m_hThread2 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread2);?? ??? ?m_hThread2 = NULL;?? ?} ?? ?if (m_hThread3 != NULL)?? ?{?? ??? ?CloseHandle(m_hThread3);?? ??? ?m_hThread3 = NULL;?? ?}} DWORD __stdcall TestCriticalSection::ThreadFun1(LPVOID lParam) //static只需要加在類定義里,類定義外面的函數定義前不能寫static{?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?//pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun1: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?//pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?} ?? ?return dRet;} DWORD __stdcall TestCriticalSection::ThreadFun2(LPVOID lParam){?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?//pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun2: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?//pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?}?? ?return dRet;} DWORD __stdcall TestCriticalSection::ThreadFun3(LPVOID lParam){?? ?DWORD dRet = TRUE;?? ?TestCriticalSection * pThis = static_cast<TestCriticalSection*>(lParam);?? ?while(1)?? ?{?? ??? ?//pThis->m_lock.Lock();?? ??? ?pThis->m_nTotals ++;?? ??? ?cout<<"ThreadFun3: m_nTotals "<<pThis->m_nTotals<<endl;?? ??? ?//pThis->m_lock.UnLock();?? ??? ?Sleep(10);?? ??? ?if (pThis->m_nTotals == 30)?? ??? ?{?? ??? ??? ?break;?? ??? ?}?? ?} ?? ?return dRet;} void TestCriticalSection::StartThread(){?? ?m_hThread1 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun1, this, ?0, NULL);?? ?m_hThread2 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun2, this, 0, NULL);?? ?m_hThread3 = CreateThread(NULL, 0, &TestCriticalSection::ThreadFun3, this, 0, NULL);}結果可能會出現下面這種狀況
原文:https://blog.csdn.net/qwerdf10010/article/details/79657821?
?
總結
以上是生活随笔為你收集整理的C++ 线程同步之临界区CRITICAL_SECTION的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三网融合情况下,实时语音通信技术的研究
- 下一篇: s3c2440移植MQTT