多線程安全的變量模板

轉自:http://blog.csdn.net/tonyxiaohome/archive/2010/01/03/5124521.aspx

作者:肖舸

多線程的變量同步問題,一直是困擾廣大VC程序員的一大難題,其主要表現是在多線程模式下,線程間共享變量的存取不再安全,程序員無法確保變量的值在存取時是否準確可信,對此,微軟給出的解決方案是使用臨界區對象加以保護。但是,臨界區對象使用太過於繁瑣,需要不斷地加鎖和解鎖,很容易搞忘,引起新的Bug。

這裏,東樓給出多線程安全的變量模板,由此模板,可派生絕大多數變量類型,實現線程間各種變量的安全互訪。本模板已經重載了幾乎全部運算符,大家可以很方便地使用++、――、+=、-=等操作,方便編程使用。



#ifndef _XiaoGeMVarTempleteHasBeenDefined_

#define _XiaoGeMVarTempleteHasBeenDefined_

#include <Afxmt.h>



template <class MVAR_TYPE>

class MVAR

{

public:

    MVAR()

    {

        m_pBegin=new char[sizeof(MVAR_TYPE)];

        memset(m_pBegin,0,sizeof(MVAR_TYPE));

    }

    ~MVAR(){delete[] m_pBegin;}

    int GetLength(){return sizeof(MVAR_TYPE);}

    MVAR_TYPE Set(MVAR_TYPE& value)

    {

        m_csLockHandle.Lock();

        memcpy(m_pBegin,(char*)&value,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return value;

    }

    MVAR_TYPE Get()

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        myValue=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator~()

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue=~myValue;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator++(int)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue++;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator++()

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue++;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator--(int)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue--;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator--()

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue--;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator+(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue+=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator-(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue-=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator*(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue*=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator/(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue/=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator&(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue&=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator|(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue|=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator^(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue^=value;

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator+=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue+=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator-=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue-=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator*=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue*=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator/=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue/=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator&=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue&=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator|=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue|=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    MVAR_TYPE operator^=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        myValue^=value;

        memcpy(m_pBegin,(char*)&myValue,sizeof(MVAR_TYPE));

        m_csLockHandle.Unlock();

        return myValue;

    }

    BOOL operator>(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue>value);

        m_csLockHandle.Unlock();

        return bRet;

    }

    BOOL operator<(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue<value);

        m_csLockHandle.Unlock();

        return bRet;

    }

    BOOL operator>=(MVAR_TYPE value)

    {

         MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue>=value);

        m_csLockHandle.Unlock();

        return bRet;

    }

    BOOL operator<=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue<=value);

        m_csLockHandle.Unlock();

        return bRet;

    }

    BOOL operator==(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue==value);

        m_csLockHandle.Unlock();

        return bRet;

    }

    BOOL operator!=(MVAR_TYPE value)

    {

        MVAR_TYPE myValue;

        BOOL bRet;

        m_csLockHandle.Lock();

        memcpy((char*)&myValue,m_pBegin,sizeof(MVAR_TYPE));

        bRet=(myValue!=value);

        m_csLockHandle.Unlock();

        return bRet;

    }

private:

    char* m_pBegin;

    CCriticalSection m_csLockHandle;

};



typedef MVAR<char>              MCHAR;

typedef MVAR<unsigned char>       MUCHAR;

typedef MVAR<short>             MSHORT;

typedef MVAR<unsigned short>    MUSHORT;

typedef MVAR<int>               MINT;

typedef MVAR<unsigned int>        MUINT;

typedef MVAR<long>              MLONG;

typedef MVAR<unsigned long>       MULONG;

typedef MVAR<float>             MFLOAT;

typedef MVAR<double>            MDOUBLE;

typedef MVAR<BOOL>              MBOOL;

typedef MVAR<LPVOID>            MLPVOID;

typedef MVAR<BYTE>              MBYTE;



#endif //_XiaoGeMVarTempleteHasBeenDefined_



    大家只需要把這段代碼放入Mvar.h文件,在stdafx.h中include這個頭文件,即可在程序中自由使用變量。以上僅僅是東樓根據自己的需要,派生的幾個常用類型,大家也可以嘗試派生新的類型使用。

    注意,當派生的變量需要取得其中的值時,必須使用.Get()成員函數,這是唯一一點不如普通變量方便的地方。

    下面給出一個控制例子,大家可以參考:



#includen “mvar.h”

class CMyClass

{

public:

    CMyClass();

    ~ CMyClass();

protected:

    static UINT MyThread(LPVOID pParam);    //線程函數

    MBOOL m_bThreadContinue;           //線程循環標誌

    MUINT m_nThreadCount;              //線程計數器

};



CMyClass::CMyClass()

{

    m_bThreadContinue=TRUE;

    m_nThreadCount=0;

    int i;

    //開啓100個線程

    for(i=0;i<100;i++)

    {

        m_nThreadCount++;                //一定要在開啓線程前累加線程計數器

        AfxBeginThread(MyThread,this);    //開啓線程,以本對象指針爲參數

}

}

CMyClass::~CMyClass()

{

    m_bThreadContinue=FALSE;  //通知線程關閉

    while(m_nThreadCount!=0) {}   //等待所有線程退出

    //此時退出,線程已經全部安全退出!!!

}

UINT CMyClass::MyThread(LPVOID pParam)

{

    CMyClass* pThis=(CMyClass*)pParam;    //得到本對象指針

    while(pThis->m_bThreadContinue)

    {

        //循環體

        Sleep(100);

}

pThis->m_nThreadCount --; //線程計數器減1

return 0;

}



如果有問題,歡迎大家提問,如果有Bug,也請大家及時向東樓提出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章