一、临界区
临界区又称关键代码段,指的是一小段代码在代码执行前,他需要独占一些资源。程序中通常将多线程同时访问的某个资源作为临界区,需要定义一个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
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(lParam);
while(1)
{
pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun1: m_nTotals "<m_nTotals<m_nTotals >= 30)
{
break;
}
pThis->m_lock.UnLock();
Sleep(10);
}
return dRet;
}
DWORD __stdcall TestCriticalSection::ThreadFun2(LPVOID lParam)
{
DWORD dRet = TRUE;
TestCriticalSection * pThis = static_cast(lParam);
while(1)
{
pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun2: m_nTotals "<m_nTotals<m_nTotals >= 30)
{
break;
}
pThis->m_lock.UnLock();
Sleep(10);
}
return dRet;
}
DWORD __stdcall TestCriticalSection::ThreadFun3(LPVOID lParam)
{
DWORD dRet = TRUE;
TestCriticalSection * pThis = static_cast(lParam);
while(1)
{
pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun3: m_nTotals "<m_nTotals<m_nTotals >= 30)
{
break;
}
pThis->m_lock.UnLock();
Sleep(10);
}
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
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(lParam);
while(1)
{
//pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun1: m_nTotals "<m_nTotals<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(lParam);
while(1)
{
//pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun2: m_nTotals "<m_nTotals<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(lParam);
while(1)
{
//pThis->m_lock.Lock();
pThis->m_nTotals ++;
cout<<"ThreadFun3: m_nTotals "<m_nTotals<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);
}
结果可能会出现下面这种状况