临界区是指程序中的多个线程访问同一个受保护的代码段,临界区的代码段同一时刻只允许一个线程执行。
使用临界区对象 CriticalSection ,来实现对临界区的操作。
下面是一些过于临界区操作的主要函数:
下面是一个临界区使用的例子:
头文件:
#include "CThread.h"
#include "Windows.h"
extern CRITICAL_SECTION g_cs;
class CirticalThread : public CThread
{
public:
void run(void) override;
};
这里我们同样使用类 CThread 来定义线程,run 函数为线程的入口函数
关于 CThread 的实现可以参照:
使用Windows API实现自定义线程类CThread
源文件:
#include "CirticalThread.h"
#include <iostream>
int testValue = 0;
// 临界区对象
CRITICAL_SECTION g_cs;
void CirticalThread::run(void)
{
while (1)
{
// 进入临界区
::EnterCriticalSection(&g_cs);
std::cout << "Test Value is " << testValue++ \
<< ", In Thread: " << ::GetCurrentThreadId() \
<< std::endl;
// 离开临界区
::LeaveCriticalSection(&g_cs);
Sleep(1000);
}
}
这里在多个线程中同时对全局变量 testValue 做自增的操作,同时打印它的值和当前的线程ID。
调用部分
int main(int argc, char** argv)
{
// 初始化临界区对象
::InitializeCriticalSection(&g_cs);
// 创建两个线程
CirticalThread thread1;
CirticalThread thread2;
// 开启线程
thread1.start();
thread2.start();
// 等待
thread1.wait();
thread2.wait();
// 销毁临界区对象
::DeleteCriticalSection(&g_cs);
system("pause");
return 0;
}
程序执行结果如下:
Test Value is 0, In Thread: 11836
Test Value is 1, In Thread: 13192
Test Value is 2, In Thread: 11836
Test Value is 3, In Thread: 13192
Test Value is 4, In Thread: 11836
Test Value is 5, In Thread: 13192
为了防止线程死锁,我们使用RALL技术。
即创造一个类对象,构造的时候进入临界区,析构的时候离开临界区。
这样临界区的进入和离开由该对象的作用域决定。
对象声明,代码如下:
class CCirticalSection
{
public:
CCirticalSection(CRITICAL_SECTION& cs);
~CCirticalSection();
private:
CRITICAL_SECTION& m_cs;
};
实现如下:
CCirticalSection::CCirticalSection(CRITICAL_SECTION& cs)
:m_cs(cs)
{
// 进入临界区
::EnterCriticalSection(&m_cs);
}
CCirticalSection::~CCirticalSection()
{
// 离开临界区
::LeaveCriticalSection(&m_cs);
}
我们修改Run函数中的内容:
void CirticalThread::run(void)
{
while (1)
{
{
CCirticalSection cs(g_cs);
std::cout << "Test Value is " << testValue++ \
<< ", In Thread: " << ::GetCurrentThreadId() \
<< std::endl;
}
Sleep(1000);
}
}