说明
临界区,类似互斥对象Mutex,用起来比较简单,速度快,是比较推荐的一种。
一般步骤:
初始化一个临界区(新建一个电话亭,只能容纳一个人)
等待进入临界区(等待进入电话亭,进入后上锁别人继续等待,如果多次上锁则要多次开锁)
离开临界区(离开电话亭要开锁,以便让其他人进入,有几道锁开几道锁,如果不开锁则别人不能进入)
删除临界区(城管把电话亭拆了)
1 初始化
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection //[out] CRITICAL_SECTION结构体指针,实际是struct _RTL_CRITICAL_SECTION类型。
);
初始化一个临界区,相当于新建一个电话亭。
eg.
CRITICAL_SECTION criticalSection;
InitializeCriticalSection(&criticalSection);
2 进入临界区
VOID EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
eg.
EnterCriticalSection(&criticalSection); //进入临界区,加锁,如果多次加锁则要有多次开锁
3 离开临界区
VOID LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
eg.
LeaveCriticalSection(&criticalSection); //离开临界区,开锁,有几道锁开几道锁
4 删除临界区
VOID DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
删除临界区,前提是临界区必须已经用InitializeCriticalSection函数创建
eg.
DeleteCriticalSection(&criticalSection);
5 实例
两个子线程分别给两个编辑框赋值,用临界区保证他们不同时更新
/74CriticalSectionDlg.h 类声明///
public:
static UINT MyThread1(LPVOID lpParam);
static UINT MyThread2(LPVOID lpParam);
private:
static CRITICAL_SECTION m_criticalSection;
/74CriticalSectionDlg.cpp 类定义/
//初始化静态成员变量,该变量为结构体,静态成员变量作为结构体的初始化采用类似形式!
CRITICAL_SECTION CMy74CriticalSectionDlg::m_criticalSection = {0};
//对话框初始化
BOOL CMy74CriticalSectionDlg::OnInitDialog()
{
//codes
InitializeCriticalSection(&m_criticalSection); //初始化临界区
CWinThread* pThread1 = AfxBeginThread(MyThread1, (LPVOID)&m_ctrlEdit1); //开启两个线程
CWinThread* pThread2 = AfxBeginThread(MyThread2, (LPVOID)&m_ctrlEdit2);
//codes
}
//子线程1
UINT CMy74CriticalSectionDlg::MyThread1(LPVOID lpParam)
{
CString str;
int a = 0;
CEdit* pEdit = (CEdit*)lpParam;
while (true)
{
EnterCriticalSection(&m_criticalSection); //等待进入临界区,进入后加锁使其他线程不能进入
str.Format("%d", ++a);
str += " a";
pEdit->SetWindowText(str);
Sleep(100);
if (a >= 1000)
{
LeaveCriticalSection(&m_criticalSection); //当a>=1000时线程1退出,如果不加此句则线程2永远不能进入临界区
break;
}
LeaveCriticalSection(&m_criticalSection); //离开 开锁
}
return 0;
}
//子线程2
UINT CMy74CriticalSectionDlg::MyThread2(LPVOID lpParam)
{
CString str;
int b = 0;
CEdit* pEdit = (CEdit*)lpParam;
while (true)
{
EnterCriticalSection(&m_criticalSection);//等待进入临界区,进入后加锁
str.Format("%d", ++b);
str += " b";
pEdit->SetWindowText(str);
Sleep(100);
LeaveCriticalSection(&m_criticalSection); //离开 开锁
}
return 0;
}
NOTE:如果子线程1或2中调用了多次EnterCriticalSection,在线程退出或一次循环结束时也要调用多次LeaveCriticalSection。