本文共 6007 字,大约阅读时间需要 20 分钟。
一、临界区临界区又称关键代码段,指的是一小段代码在代码执行前,他需要独占一些资源。程序中通常将多线程同时访问的某个资源作为临界区,需要定义一个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