• 临界区(Critical Section)的封装和使用示例


    向我老大致敬!

    这个做法其实是抄我老大的。服务器中,多线程经常需要使用临界区,为了简化代码的使用,把临界区封装为 CThreadLockHandle  类,通过封装,使用临界区资源每次只需要一行代码,而且只要确定对象的生存周期,就能完成对临界区资源的自动释放:

    头文件:

    //thread_lock.h
    #ifndef THREAD_LOCK_HEAD_FILE
    #define THREAD_LOCK_HEAD_FILE
    #include<windows.h>
    ////////////////////////////////////////////////////////////////////////////
    
    //临界区同步类
    class CThreadLock
    {
        //变量定义
    private:
        CRITICAL_SECTION                m_csLock;            //临界区变量
    
        //函数定义
    public:
        //构造函数
        inline CThreadLock() {    ::InitializeCriticalSection(&m_csLock);    };
        //析构函数
        inline ~CThreadLock() {    ::DeleteCriticalSection(&m_csLock);    };
    
        //功能函数
    public:
        //锁定函数
        inline void Lock() {    ::EnterCriticalSection(&m_csLock); };
        //解锁函数
        inline void UnLock() {    ::LeaveCriticalSection(&m_csLock); };
    };
    
    ////////////////////////////////////////////////////////////////////////////
    
    //安全同步锁定句柄
    class CThreadLockHandle
    {
        //变量定义
    private:
        int                                m_nLockCount;        //锁定计数
        CThreadLock                        *m_pThreadLock;        //锁定对象
    
        //函数定义
    public:
        //构造函数
        CThreadLockHandle(CThreadLock *pThreadLock, bool bAutoLock=true);
        //析构函数
        virtual ~CThreadLockHandle();
    
        //功能函数
    public:
        //锁定函数
        void Lock();
        //解锁函数
        void UnLock();
        //火枪锁定次数
        int inline GetLockCount() {    return m_nLockCount; };
    };
    
    #endif

    源文件:

    //thread_lock.cpp   programed by sany
    //2014.9.2
    //callme:sanyue9394@163.com
    
    
    #include "thread_lock.h"
    #include<assert.h>
    ////////////////////////////////////////////////////////////////////////////
    
    //安全同步锁定句柄
    //构造函数
    CThreadLockHandle::CThreadLockHandle(CThreadLock *pThreadLock, bool bAutoLock)
    {
        assert(pThreadLock!=NULL);
        m_nLockCount=0;
        m_pThreadLock=pThreadLock;
        if(bAutoLock)    Lock();
        return;
    }
    //析构函数
    CThreadLockHandle::~CThreadLockHandle()
    {
        while(m_nLockCount>0) UnLock();                                //生存周期结束自动解锁
    }
    
    //锁定函数
    void CThreadLockHandle::Lock()
    {
        //校验状态
        assert(m_nLockCount>=0);
        assert(m_pThreadLock!=NULL);
    
        //锁定对象
        m_nLockCount++;
        m_pThreadLock->Lock();
    }
    
    //解锁函数
    void CThreadLockHandle::UnLock()
    {
        //校验状态
        assert(m_nLockCount>0);
        assert(m_pThreadLock!=NULL);
    
        //解除状态
        m_nLockCount--;
        m_pThreadLock->UnLock();
    }

    经过这个类的封装,使用临界区实现线程同步只需要2步:

    1.初始化一个全局的 CThreadLock 对象,为后面调用做准备。

    2.每当需要使用临界区时,在作用域中声明一个局部变量:CThreadLockHandle ,当其生存周期结束时,将自动释放临界区资源

    使用例子:

    #include<stdio.h>
    #include<windows.h>
    #include <process.h> 
    #include"thread_lock.h"
    
    const int aSize=10;
    char szArr[aSize+1]={};
    
    CThreadLock                        threadLock;                            //声明CThreadLock类型的全局变量
    
    unsigned _stdcall threadFunc1(void*)
    {
        CThreadLockHandle lockHandle(&threadLock);                        //需要使用临界区是,声明一个CThreadLockHandle类型的变量,其生存周期结束自动解锁
        for(int s=0;s<aSize;s++)
        {
            szArr[s]='a';
            Sleep(1);
        }
        return 0;
    }
    
    unsigned _stdcall threadFunc2(void*)
    {
        CThreadLockHandle lockHandle(&threadLock);                        //需要使用临界区是,声明一个CThreadLockHandle类型的变量,其生存周期结束自动解锁
        for(int s=0;s<aSize;s++)
        {
            szArr[aSize-1-s]='b';
            Sleep(1);
        }
        return 0;
    }
    
    int main()
    {
        memset(szArr,0,sizeof(szArr));
        HANDLE handle1=(HANDLE)_beginthreadex(NULL,0,threadFunc1,NULL,0,0);
        HANDLE handle2=(HANDLE)_beginthreadex(NULL,0,threadFunc2,NULL,0,0);
    
        WaitForSingleObject(handle1,INFINITE);
        WaitForSingleObject(handle2,INFINITE);
    
        printf("%s
    ",szArr);
        CloseHandle(handle1);
        CloseHandle(handle2);
    
        return 0;
    }

    如果在类中调用,把CThreadLock 对象声明为私有或保护成员即可:

    class threadtest
    {
    protected:
        static CThreadLock                        m_ThreadLock;                //线程锁
    
    public:
        static unsigned _stdcall threadFunction(void* pThreadData);
    };
    unsigned _stdcall threadtest::threadFunction(void* pThreadData)
    {
        CThreadLockHandle lockHandle(&m_ThreadLock);                //生存周期结束自动解锁
        //doSomething
        return 0;
    }

      附:http://www.cnblogs.com/userinterface/archive/2005/04/27/146137.html    不错的线程同步文章

  • 相关阅读:
    DevOps系列【gitlab如何新建项目仓库?】
    Redis系列【docker带密码进入redis】
    Vue系列【js把一个类对象数组抽取类中几个属性重新组成新的类对象数组】
    一句话概括SSO和OAuth2.0
    CListCtrl控件使用指南(大全)
    CListCtrl的主要事件及鼠标响应函数
    c语言动态内存分配(上课)
    OSPF 路由聚合
    华为 OSPF基本配置
    OSPF NSSA区域
  • 原文地址:https://www.cnblogs.com/sixbeauty/p/3951406.html
Copyright © 2020-2023  润新知