线程锁EnterCriticalSection和LeaveCriticalSection的用法

VC 专栏收录该内容
8 篇文章 0 订阅
线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法
注:使用结构CRITICAL_SECTION 需加入头文件#include “afxmt.h”
定义一个全局的锁 CRITICAL_SECTION的实例
  和一个静态全局变量
CRITICAL_SECTION cs;//可以理解为锁定一个资源
static int n_AddValue = 0;//定义一个静态的全部变量n_AddValue
创建两个线程函数,代码实现如下:
//第一个线程
UINT FirstThread(LPVOID lParam)
{
EnterCriticalSection(&cs);//加锁 接下来的代码处理过程中不允许其他线程进行操作,除非遇到LeaveCriticalSection
for(int i = 0; i<10; i++){
n_AddValue ++;
cout << "n_AddValue in FirstThread is "<<n_AddValue <<endl;
}
LeaveCriticalSection(&cs);//解锁 到EnterCriticalSection之间代码资源已经释放了,其他线程可以进行操作
return 0;
}
//第二个线程
UINT SecondThread(LPVOID lParam)
{
EnterCriticalSection(&cs);//加锁
for(int i = 0; i<10; i++){
n_AddValue ++;
cout << "n_AddValue in SecondThread is "<<n_AddValue <<endl;
}
LeaveCriticalSection(&cs);//解锁
return 0;
}
在主函数添加以下代码
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败/n"));
nRetCode = 1;
}
else
{
InitializeCriticalSection(&cs);//初始化结构CRITICAL_SECTION
CWinThread *pFirstThread,*pSecondThread;//存储函数AfxBeginThread返回的CWinThread指针
pFirstThread = AfxBeginThread(FirstThread,LPVOID(NULL));//启动第一个线程
pSecondThread = AfxBeginThread(SecondThread,LPVOID(NULL));//启动第二个线程
HANDLE hThreadHandle[2];//
hThreadHandle[0] = pFirstThread->m_hThread;
hThreadHandle[1] = pSecondThread->m_hThread;
//等待线程返回
WaitForMultipleObjects(2,hThreadHandle,TRUE,INFINITE);
}
DeleteCriticalSection(&cs);//删除临界区
return nRetCode;
}
输出:
n_AddValue in FirstThread is 1
  n_AddValue in FirstThread is 2
  n_AddValue in FirstThread is 3
  n_AddValue in FirstThread is 4
  n_AddValue in FirstThread is 5
  n_AddValue in FirstThread is 6
  n_AddValue in FirstThread is 7
  n_AddValue in FirstThread is 8
  n_AddValue in FirstThread is 9
  n_AddValue in FirstThread is 10
  n_AddValue in SecondThread is 11
  n_AddValue in SecondThread is 12
  n_AddValue in SecondThread is 13
  n_AddValue in SecondThread is 14
  n_AddValue in SecondThread is 15
  n_AddValue in SecondThread is 16
  n_AddValue in SecondThread is 17
  n_AddValue in SecondThread is 18
  n_AddValue in SecondThread is 19
  n_AddValue in SecondThread is 20
如果把两个线程函数中的EnterCriticalSection和LeaveCriticalSection位置移到for循环中去,线程的执行顺序将会改变
  输出也就跟着改变,如:
//第一个线程
UINT FirstThread(LPVOID lParam)
{
for(int i = 0; i<10; i++){
EnterCriticalSection(&cs);//加锁 锁移到for循环内部里
n_AddValue ++;
cout << "n_AddValue in FirstThread is "<<n_AddValue <<endl;
LeaveCriticalSection(&cs);//解锁
}
return 0;
}
//第二个线程
UINT SecondThread(LPVOID lParam)
{
for(int i = 0; i<10; i++){
EnterCriticalSection(&cs);//加锁
n_AddValue ++;
cout << "n_AddValue in SecondThread is "<<n_AddValue <<endl;
LeaveCriticalSection(&cs);//解锁
}
return 0;
}
其他代码不变,输出的结果如下:
n_AddValue in FirstThread is 1
  n_AddValue in SecondThread is 2
  n_AddValue in FirstThread is 3
  n_AddValue in SecondThread is 4
  n_AddValue in FirstThread is 5
  n_AddValue in SecondThread is 6
  n_AddValue in FirstThread is 7
  n_AddValue in SecondThread is 8
  n_AddValue in FirstThread is 9
  n_AddValue in SecondThread is 10
  n_AddValue in FirstThread is 11
  n_AddValue in SecondThread is 12
  n_AddValue in FirstThread is 13
  n_AddValue in SecondThread is 14
  n_AddValue in FirstThread is 15
  n_AddValue in SecondThread is 16
  n_AddValue in FirstThread is 17
  n_AddValue in SecondThread is 18
  n_AddValue in FirstThread is 19
  n_AddValue in SecondThread is 20
个人认为在函数EnterCriticalSection和LeaveCriticalSection中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
  的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性 [2]  
使用EnterCriticalSection与LeaveCriticlSection时应注意
若在同一个线程中第一次LeaveCriticlSection与第二次EnterCriticalSection执行间隔较短(如一个循环内的最后一行与第一行),可能导致其他线程无法进入临界区。此时可在LeaveCriticlSection后适当延时。
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for(;;)
{
EnterCriticalSection(&cs);
cout << "In ThreadProc2" << endl;
LeaveCriticalSection(&cs);
Sleep(100);//若去掉此句 可能导致其他线程无法进入临界区
}
}
  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值