线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法


使用结构CRITICAL_SECTION 需加入头文件#include “afxmt.h”

定义一个全局的锁 CRITICAL_SECTION的实例
和一个静态全局变量


CRITICAL_SECTION cs;//可以理解为锁定一个资源
static int n_AddValue = 0;//定义一个静态的全部变量n_AddValue


创建两个线程函数,代码实现如下:


线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法_加锁

代码


//第一个线程
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;
}


 

在主函数添加以下代码




线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法_加锁

代码


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);       
    }
 
    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循环中去,线程的执行顺序将会改变
输出也就跟着改变,如:

 


线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法_加锁

代码

//第一个线程
 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中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性