线程锁EnterCriticalSection和LeaveCriticalSection的用法

2022-09-29 10:18:55 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

线程锁的概念函数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);//若去掉此句 可能导致其他线程无法进入临界区

}

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/192883.html原文链接:https://javaforall.cn

0 人点赞