您的位置:首页 > 其它

临界区锁 InitializeCriticalSection()--- EnterCriticalSection()--LeaveCriticalSection()

2016-12-05 16:04 537 查看
[+]
















1、




InitializeCriticalSection

此函数初始化一个临界区对象。

格式:

void InitializeCriticalSection(  LPCRITICAL_SECTION lpCriticalSection);

参数:lpCriticalSection指向临界区对象的指针。

返回值:无

      单个进程的线程可以使用一个互斥同步临界区对象。虽然对线程将获得临界区所有权的顺序没有保证,该系统将处理所有线程的所有权要求。

这个进程负责分配一个临界区对象使用的内存,它可以通过声明类型的CRITICAL_SECTION的变量使用的内存。在使用一个临界区对象以前,一些进程中的线程必须调用InitializeCriticalSection函数来初始化对象。

一旦一个临界区对象已被初始化,该进程的线程可以在EnterCriticalSection或LeaveCriticalSection函数指定对象,提供对共享资源的相互独占式访问。对于不同进程之间的类似线程同步,使用互斥对象。

一个临界区对象不能移动或复制。这一进程也绝不能修改该对象,但必须把它作为逻辑不透明来处理。只能使用由与Microsoft Win32 ® API提供的临界区功能,用来管理临界区对象。

在低内存的情况下,InitializeCriticalSection可能提出STATUS_NO_MEMORY异常。

========


2、DeleteCriticalSection

删除关键节对象释放由该对象使用的所有系统资源。


  void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);


参数:  lpCriticalSection, 对关键节对象的指针。先前必须已将该对象初始化与InitializeCriticalSection函数中。


=================

3、线程锁的概念函数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); 
     
    }
 
    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中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中

的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: