藍森林首頁 | 返回主頁 | 本站地圖 | 站內搜索 | 聯繫信箱 |
 您目前的位置:首頁 > 自由軟件 > 技術交流 > 應用編程


    

藍森林 http://www.lslnet.com 2006年6月6日 10:18


在網上找的一個有用的讀寫鎖

讀寫鎖,作用:
可以用在對於一個資源要實現多個用戶讀,多個用戶寫的情況下,可以避免同時有多個用戶寫該資源,但是可以有多個用戶同時讀,但是不能在有用戶讀的同時,有用戶寫的情況下:
我在網上找了個實現代碼,大家看看,怎麼樣?(TestClass是我寫的);
// TestMFC.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "vector"
#include "TestMFC.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;
#ifndef __MUTEX_READERS_WRITERS
#define __MUTEX_READERS_WRITERS

class CMutexRW
{
protected:
        HANDLE                m_semReaders;
        HANDLE                m_semWriters;
        int                        m_nReaders;
public:
        CMutexRW() :
                m_semReaders(NULL),
                m_semWriters(NULL),
                m_nReaders(0)
        {
                // initialize the Readers & Writers variables
                m_semReaders        = ::CreateSemaphore(NULL, 1, 1, NULL);
                m_semWriters        = ::CreateSemaphore(NULL, 1, 1, NULL);
                m_nReaders                = 0;

                if (m_semReaders == NULL || m_semWriters == NULL)
                {
                        LPVOID lpMsgBuf;
                        FormatMessage(
                                FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                FORMAT_MESSAGE_FROM_SYSTEM |
                                FORMAT_MESSAGE_IGNORE_INSERTS,
                                NULL,
                                GetLastError(),
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                (LPTSTR) &lpMsgBuf,
                                0,
                                NULL
                                );
                        TRACE( "***** ERROR: CreateSemaphore: %s\n", (LPCTSTR)lpMsgBuf );
                        LocalFree( lpMsgBuf );                       
                }
        };

        virtual ~CMutexRW()
        {
                if (m_semWriters)
                        VERIFY( ::CloseHandle(m_semWriters) );       

                m_semWriters = NULL;
                if (m_semReaders)
                        VERIFY( ::CloseHandle(m_semReaders) );       
                m_semReaders = NULL;
        }

        inline void Lock_DataRead(){
                DWORD dwEvent = WAIT_TIMEOUT;

                // P( semReaders )
                dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
                ASSERT(dwEvent == WAIT_OBJECT_0);

                m_nReaders++;

                if (m_nReaders == 1)
                {
                        // P( semWriters )
                        dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
                        ASSERT(dwEvent == WAIT_OBJECT_0);
                }
                // V( semReaders )
                VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
        };

        inline void Unlock_DataRead(){
                DWORD dwEvent = WAIT_TIMEOUT;
                // P( semReaders )
                dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
                ASSERT(dwEvent == WAIT_OBJECT_0);

                m_nReaders--;

                if (m_nReaders == 0)
                {
                        // V( semWriters )
                        VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
                }
                // V( semReaders )
                VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
        };

        inline void Lock_DataWrite(){
                DWORD dwEvent = WAIT_TIMEOUT;

                // P( semWriters )
                dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
                ASSERT(dwEvent == WAIT_OBJECT_0);
        }

        inline void Unlock_DataWrite(){
                // V( semWriters )
                VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
        };

};

class CReadLock
{
protected:
        CMutexRW*        m_pMutexRW;
        bool                m_bIsLocked;
public:
        CReadLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
                m_pMutexRW(pMutexRW), m_bIsLocked(false)
        {
                ASSERT(m_pMutexRW);
                if (bInitialLock){
                        m_pMutexRW->;Lock_DataRead();
                        m_bIsLocked = true;
                }
        };

        inline const bool& IsLocked() const{
                return m_bIsLocked;
        };

        inline void Lock(){
                ASSERT(m_bIsLocked == false);
                m_pMutexRW->;Lock_DataRead();
                m_bIsLocked = true;
        };

        inline void Unlock(){
                ASSERT(m_bIsLocked);
                m_pMutexRW->;Unlock_DataRead();
                m_bIsLocked = false;
        };
        virtual ~CReadLock(){
                if (m_bIsLocked){
                        m_pMutexRW->;Unlock_DataRead();
                }
        };
};

class CWriteLock
{
protected:
        CMutexRW*        m_pMutexRW;
        bool                m_bIsLocked;
public:
        CWriteLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
                m_pMutexRW(pMutexRW), m_bIsLocked(false)
        {
                ASSERT(m_pMutexRW);
                if (bInitialLock){
                        m_pMutexRW->;Lock_DataWrite();
                        m_bIsLocked = true;
                }
        };

        inline const bool& IsLocked() const{
                return m_bIsLocked;
        };

        inline void Lock(){
                ASSERT(m_bIsLocked == false);
                m_pMutexRW->;Lock_DataWrite();
                m_bIsLocked = true;
        };

        inline void Unlock(){
                ASSERT(m_bIsLocked);
                m_pMutexRW->;Unlock_DataWrite();
                m_bIsLocked = false;
        };
        virtual ~CWriteLock(){
                if (m_bIsLocked){
                        m_pMutexRW->;Unlock_DataWrite();
                }
        };
};

#endif // end #ifndef __MUTEX_READERS_WRITERS
static int ThreadID;
CMutexRW m_Mutex;
class TestClass
{
public:
       
        std::vector<HANDLE>; ThreadArray;
public:
        static DWORD WINAPI Thread_Read(LPVOID nParament)
        {
                int ID= ThreadID;
                ThreadID++;       
                m_Mutex.Lock_DataRead();
                for(int i =0 ;i<4;i++)
                {
                printf("reading:%d\n",ID);
                ::Sleep(100);
                }
                m_Mutex.Unlock_DataRead();
                return 1;
        };
        static DWORD WINAPI Thread_Write(LPVOID nParament)
        {
                int ID = ThreadID;
                ThreadID++;
                m_Mutex.Lock_DataWrite();
                for(int i=0;i<4;i++)
                {       
                printf("writing:%d\n",ID);
                ::Sleep(100);
                }
                m_Mutex.Unlock_DataWrite();
                return 1;
        };
        void Test()
        {
                for(int i=0;i<10;i++)
                {
                        if(i/2 == 1)
                        {
                HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Read,0,0,NULL);
                ThreadArray.push_back(ThreadHandle);       
                        }
                        else
                        {
                HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Write,0,0,NULL);
                ThreadArray.push_back(ThreadHandle);       
                        }
                };
        };
        void  About()
        {
                int i=0;
                while(1)
                {  
                        ::Sleep(100);       
                        HANDLE ThreadHandle = ThreadArray[i];
                        DWORD ExitCode;
                        ::GetExitCodeThread(ThreadHandle,&ExitCode);
                        if(ExitCode !=STILL_ACTIVE)
                        {
                                i++;
                                if(i == ThreadArray.size())
                                        return ;
                        }
                        else
                                i=0;
                }
        }
public:
        TestClass(){ThreadID = 0;};
        ~TestClass(){About();};
};


int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
       
        int nRetCode = 0;

        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
                // TODO: change error code to suit your needs
                cerr << _T("Fatal Error: MFC initialization failed") << endl;
                nRetCode = 1;
        }
        else
        {
                // TODO: code your application's behavior here.
                CString strHello;
                strHello.LoadString(IDS_HELLO);
                cout << (LPCTSTR)strHello << endl;
                TestClass m_Test;
                m_Test.Test();
        }

        return nRetCode;
}

在網上找的一個有用的讀寫鎖

用code對齊
這樣大家看起來都方便
[code]
// TestMFC.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "vector"
#include "TestMFC.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;
#ifndef __MUTEX_READERS_WRITERS
#define __MUTEX_READERS_WRITERS

class CMutexRW
{
        protected:
                HANDLE m_semReaders;
                HANDLE m_semWriters;
                int m_nReaders;
        public:
                CMutexRW() :
                        m_semReaders(NULL),
                m_semWriters(NULL),
                m_nReaders(0)
                {
                        // initialize the Readers & Writers variables
                        m_semReaders = ::CreateSemaphore(NULL, 1, 1, NULL);
                        m_semWriters = ::CreateSemaphore(NULL, 1, 1, NULL);
                        m_nReaders = 0;

                        if (m_semReaders == NULL || m_semWriters == NULL)
                        {
                                LPVOID lpMsgBuf;
                                FormatMessage(
                                                FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                                FORMAT_MESSAGE_FROM_SYSTEM |
                                                FORMAT_MESSAGE_IGNORE_INSERTS,
                                                NULL,
                                                GetLastError(),
                                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                                (LPTSTR) &lpMsgBuf,
                                                0,
                                                NULL
                                             );
                                TRACE( "***** ERROR: CreateSemaphore: %s\n", (LPCTSTR)lpMsgBuf );
                                LocalFree( lpMsgBuf );
                        }
                };

                virtual ~CMutexRW()
                {
                        if (m_semWriters)
                                VERIFY( ::CloseHandle(m_semWriters) );

                        m_semWriters = NULL;
                        if (m_semReaders)
                                VERIFY( ::CloseHandle(m_semReaders) );
                        m_semReaders = NULL;
                }

                inline void Lock_DataRead(){
                        DWORD dwEvent = WAIT_TIMEOUT;

                        // P( semReaders )
                        dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
                        ASSERT(dwEvent == WAIT_OBJECT_0);

                        m_nReaders++;

                        if (m_nReaders == 1)
                        {
                                // P( semWriters )
                                dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
                                ASSERT(dwEvent == WAIT_OBJECT_0);
                        }
                        // V( semReaders )
                        VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
                };

                inline void Unlock_DataRead(){
                        DWORD dwEvent = WAIT_TIMEOUT;
                        // P( semReaders )
                        dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
                        ASSERT(dwEvent == WAIT_OBJECT_0);

                        m_nReaders--;

                        if (m_nReaders == 0)
                        {
                                // V( semWriters )
                                VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
                        }
                        // V( semReaders )
                        VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
                };

                inline void Lock_DataWrite(){
                        DWORD dwEvent = WAIT_TIMEOUT;

                        // P( semWriters )
                        dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
                        ASSERT(dwEvent == WAIT_OBJECT_0);
                }

                inline void Unlock_DataWrite(){
                        // V( semWriters )
                        VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
                };

};

class CReadLock
{
        protected:
                CMutexRW* m_pMutexRW;
                bool m_bIsLocked;
        public:
                CReadLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
                        m_pMutexRW(pMutexRW), m_bIsLocked(false)
                        {
                                ASSERT(m_pMutexRW);
                                if (bInitialLock){
                                        m_pMutexRW->;Lock_DataRead();
                                        m_bIsLocked = true;
                                }
                        };

                inline const bool& IsLocked() const{
                        return m_bIsLocked;
                };

                inline void Lock(){
                        ASSERT(m_bIsLocked == false);
                        m_pMutexRW->;Lock_DataRead();
                        m_bIsLocked = true;
                };

                inline void Unlock(){
                        ASSERT(m_bIsLocked);
                        m_pMutexRW->;Unlock_DataRead();
                        m_bIsLocked = false;
                };
                virtual ~CReadLock(){
                        if (m_bIsLocked){
                                m_pMutexRW->;Unlock_DataRead();
                        }
                };
};

class CWriteLock
{
        protected:
                CMutexRW* m_pMutexRW;
                bool m_bIsLocked;
        public:
                CWriteLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
                        m_pMutexRW(pMutexRW), m_bIsLocked(false)
                        {
                                ASSERT(m_pMutexRW);
                                if (bInitialLock){
                                        m_pMutexRW->;Lock_DataWrite();
                                        m_bIsLocked = true;
                                }
                        };

                inline const bool& IsLocked() const{
                        return m_bIsLocked;
                };

                inline void Lock(){
                        ASSERT(m_bIsLocked == false);
                        m_pMutexRW->;Lock_DataWrite();
                        m_bIsLocked = true;
                };

                inline void Unlock(){
                        ASSERT(m_bIsLocked);
                        m_pMutexRW->;Unlock_DataWrite();
                        m_bIsLocked = false;
                };
                virtual ~CWriteLock(){
                        if (m_bIsLocked){
                                m_pMutexRW->;Unlock_DataWrite();
                        }
                };
};

#endif // end #ifndef __MUTEX_READERS_WRITERS
static int ThreadID;
CMutexRW m_Mutex;
class TestClass
{
        public:

                std::vector<HANDLE>; ThreadArray;
        public:
                static DWORD WINAPI Thread_Read(LPVOID nParament)
                {
                        int ID= ThreadID;
                        ThreadID++;
                        m_Mutex.Lock_DataRead();
                        for(int i =0 ;i<4;i++)
                        {
                                printf("reading:%d\n",ID);
                                ::Sleep(100);
                        }
                        m_Mutex.Unlock_DataRead();
                        return 1;
                };
                static DWORD WINAPI Thread_Write(LPVOID nParament)
                {
                        int ID = ThreadID;
                        ThreadID++;
                        m_Mutex.Lock_DataWrite();
                        for(int i=0;i<4;i++)
                        {
                                printf("writing:%d\n",ID);
                                ::Sleep(100);
                        }
                        m_Mutex.Unlock_DataWrite();
                        return 1;
                };
                void Test()
                {
                        for(int i=0;i<10;i++)
                        {
                                if(i/2 == 1)
                                {
                                        HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Read,0,0,NULL);
                                        ThreadArray.push_back(ThreadHandle);
                                }
                                else
                                {
                                        HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Write,0,0,NULL);
                                        ThreadArray.push_back(ThreadHandle);
                                }
                        };
                };
                void About()
                {
                        int i=0;
                        while(1)
                        {
                                ::Sleep(100);
                                HANDLE ThreadHandle = ThreadArray[i];
                                DWORD ExitCode;
                                ::GetExitCodeThread(ThreadHandle,&ExitCode);
                                if(ExitCode !=STILL_ACTIVE)
                                {
                                        i++;
                                        if(i == ThreadArray.size())
                                                return ;
                                }
                                else
                                        i=0;
                        }
                }
        public:
                TestClass(){ThreadID = 0;};
                ~TestClass(){About();};
};


int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{

        int nRetCode = 0;

        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
                // TODO: change error code to suit your needs
                cerr << _T("Fatal Error: MFC initialization failed") << endl;
                nRetCode = 1;
        }
        else
        {
                // TODO: code your application's behavior here.
                CString strHello;
                strHello.LoadString(IDS_HELLO);
                cout << (LPCTSTR)strHello << endl;
                TestClass m_Test;
                m_Test.Test();
        }

        return nRetCode;
}


[/code]

在網上找的一個有用的讀寫鎖

有 c嗎



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 藍森林網站 版權所有。 E-mail : webmaster@lslnet.com