单写入多读取进程锁

来源:互联网 发布:杀死汝爱真实事件 知乎 编辑:程序博客网 时间:2024/05/28 03:02

只读线程锁原理 & 只读进程锁原理

只读线程锁代码实现

#ifndef MYLOCK_H__ // 2017-11-15 16:13:57 MyLock.h#define MYLOCK_H__/** @class CMyLock *  @brief 本锁既是线程锁也是进程锁,适用于一下4种情况 *  1) 当一个线程(或进程)正在写入数据时,其他任何线程(或进程)不能写入数据    2) 当一个线程(或进程)正在写入数据时,其他任何线程(或进程)不能读取数据    3) 当一个线程(或进程)正在读取数据时,其他任何线程(或进程)不能写入数据    4) 当一个线程(或进程)正在读取数据时,其他线程(或进程)也能够读取数据。 */class CMyLock{public:    explicit CMyLock();             // 构造函数    virtual ~CMyLock();             // 析构函数    void ReadStart();               // 读取开始,必须与ReadEnd成对使用    void ReadEnd();                 // 读取结束,必须与ReadStart成对使用    void WriteStart();              // 写入开始,必须与WriteEnd成对使用    void WriteEnd();                // 写入结束,必须与WriteStart成对使用private:    void *  m_pcs;                  // 本类的成员变量锁    int     m_nWaitingReaders;      // 目前等待状态中的读取者的个数    int     m_nWaitingWriters;      // 目前等待状态中的写入者的个数    int     m_nActiveReaders;       // 目前正在读取状态的读取者的个数    int     m_nActiveWriters;       // 目前正在写入状态的写入者的个数(现在只能是1,后续根据需求更改)    void *  m_hSemReaders;          // 所有读取者应该等待的信号量,该信号量由WriteEnd触发    void *  m_hSemWriters;          // 所有写入者应该等待的信号量,该信号量由ReadEnd或WriteEnd触发}; // CMyLock#endif // MYLOCK_H__
#include "MyLock.h" // MyLock.cpp#include <Windows.h>CMyLock::CMyLock(){    InitializeCriticalSection((CRITICAL_SECTION *)(m_pcs = new CRITICAL_SECTION));    m_nWaitingReaders   = 0;    m_nWaitingWriters   = 0;    m_nActiveReaders    = 0;    m_nActiveWriters    = 0;    m_hSemReaders       = CreateSemaphore(NULL, 0, MAXLONG, NULL);    m_hSemWriters       = CreateSemaphore(NULL, 0, MAXLONG, NULL);}CMyLock::~CMyLock(){    CloseHandle(m_hSemWriters);    CloseHandle(m_hSemReaders);    m_nWaitingWriters   = 0;    m_nActiveReaders    = 0;    m_nActiveWriters    = 0;    m_nWaitingReaders   = 0;    DeleteCriticalSection((CRITICAL_SECTION *)(m_pcs));}void CMyLock::ReadStart(){    EnterCriticalSection((CRITICAL_SECTION *)m_pcs);    bool bWait = (m_nActiveWriters | m_nWaitingWriters);    if (bWait)  // 读比写的优先级低,所以由Waiting的Writers,那么Reader等待    {        m_nWaitingReaders++;    }    else    {        m_nActiveReaders++;    }    LeaveCriticalSection((CRITICAL_SECTION *)m_pcs);    if (bWait)  // 等待WriteEnd释放m_hSemReaders信号量    {        WaitForSingleObject(m_hSemReaders, INFINITE);    }}void CMyLock::ReadEnd(){    EnterCriticalSection((CRITICAL_SECTION *)m_pcs);    m_nActiveReaders--;    void *  hTempSem            = NULL;    int     nReleaseSemCount    = 0;    if (0 == m_nActiveReaders)  // 所有读取者读取动作完成,需要释放信号量让其他对象获得权限    {        if (0 < m_nWaitingWriters)      // 写入者优先级高        {            m_nWaitingWriters--;            m_nActiveWriters++;         // 相当于m_nActiveWriters = 1            hTempSem            = m_hSemWriters;            nReleaseSemCount    = 1;    // 一次释放一个写入信号量        }        else if (0 < m_nWaitingReaders)        {            m_nActiveReaders    = m_nWaitingReaders;            m_nWaitingReaders   = 0;            hTempSem            = m_hSemReaders;            nReleaseSemCount    = m_nActiveReaders; // 一次性释放所有读取信号量        }    }    LeaveCriticalSection((CRITICAL_SECTION *)m_pcs);    if (hTempSem)    {        ReleaseSemaphore(hTempSem, nReleaseSemCount, NULL);    }}void CMyLock::WriteStart(){    EnterCriticalSection((CRITICAL_SECTION *)m_pcs);    bool bWait = (m_nActiveReaders | m_nActiveWriters | m_nWaitingWriters);    if (bWait)  // 读比写的优先级低,所以不用管是否有Waiting状态的Readers    {        m_nWaitingWriters++;    }    else    {        m_nActiveWriters++;    }    LeaveCriticalSection((CRITICAL_SECTION *)m_pcs);    if (bWait)  // 读比写的优先级低,所以不用管是否有Waiting状态的Readers    {        WaitForSingleObject(m_hSemWriters, INFINITE);    }}void CMyLock::WriteEnd(){    EnterCriticalSection((CRITICAL_SECTION *)m_pcs);    m_nActiveWriters--;    void *  hTempSem            = NULL;    int     nReleaseSemCount    = 0;    if (0 == m_nActiveWriters)  // 本次写入完成,需要释放信号量让其他对象获得权限    {        if (0 < m_nWaitingWriters)      // 写入者优先级高        {            m_nWaitingWriters--;            m_nActiveWriters++;         // 相当于m_nActiveWriters = 1            hTempSem            = m_hSemWriters;            nReleaseSemCount    = 1;    // 一次释放一个写入信号量        }        else if (0 < m_nWaitingReaders)        {            m_nActiveReaders    = m_nWaitingReaders;            m_nWaitingReaders   = 0;            hTempSem            = m_hSemReaders;            nReleaseSemCount    = m_nActiveReaders; // 一次性释放所有读取信号量        }    }    LeaveCriticalSection((CRITICAL_SECTION *)m_pcs);    if (hTempSem)    {        ReleaseSemaphore(hTempSem, nReleaseSemCount, NULL);    }}

只读进程锁代码实现

#ifndef MYLOCK_H__ // 2017-11-15 16:13:57#define MYLOCK_H__/** @class CMyLock *  @brief 本锁既是线程锁也是进程锁,适用于一下4种情况 *  1) 当一个(或多个)线程(或进程)正在写入数据时,其他任何线程(或进程)不能写入数据    2) 当一个(或多个)线程(或进程)正在写入数据时,其他任何线程(或进程)不能读取数据    3) 当一个(或多个)线程(或进程)正在读取数据时,其他任何线程(或进程)不能写入数据    4) 当一个(或多个)线程(或进程)正在读取数据时,其他线程(或进程)也能够读取数据。 */class CMyLock{public:    explicit CMyLock(const char * const strLockID = 0); // 构造函数    virtual ~CMyLock();             // 析构函数    void ReadStart();               // 读取开始,必须与ReadEnd成对使用    void ReadEnd();                 // 读取结束,必须与ReadStart成对使用    void WriteStart();              // 写入开始,必须与WriteEnd成对使用    void WriteEnd();                // 写入结束,必须与WriteStart成对使用private:    void *  m_hMutex;               // 本类的成员变量进程锁    void *  m_hFileMapping;         // 获取文件映射从而获取成员变量    void *  m_hSemReaders;          // 所有读取者应该等待的信号量,该信号量由WriteEnd触发    void *  m_hSemWriters;          // 所有写入者应该等待的信号量,该信号量由ReadEnd或WriteEnd触发}; // CMyLock#endif // MYLOCK_H__
#include "MyLock.h"#include <Windows.h>#include <assert.h>#include <stdio.h>typedef struct MY_FILE_MAPPING_INFO__{    int     m_nWaitingReaders;    int     m_nWaitingWriters;    int     m_nActiveReaders;    int     m_nActiveWriters;} MY_FILE_MAPPING_INFO;#define MAX_FILE_MAPPING_LENGTH sizeof(MY_FILE_MAPPING_INFO)CMyLock::CMyLock(const char * const strLockID){    assert(strLockID);    char strMutexName[MAX_PATH] = {0};    char strFileMappingName[MAX_PATH] = {0};    char strSemReadersName[MAX_PATH] = {0};    char strSemWritersName[MAX_PATH] = {0};    _snprintf_s(strMutexName, MAX_PATH, MAX_PATH - 1, "%s+Mutex");    _snprintf_s(strFileMappingName, MAX_PATH, MAX_PATH - 1, "%s+FileMapping");    _snprintf_s(strSemReadersName, MAX_PATH, MAX_PATH - 1, "%s+SemReaders");    _snprintf_s(strSemWritersName, MAX_PATH, MAX_PATH - 1, "%s+SemWriters");    m_hMutex            = CreateMutex(0, 0, strMutexName);   assert(m_hMutex);    WaitForSingleObject(m_hMutex, INFINITE);    m_hFileMapping      = CreateFileMapping(INVALID_HANDLE_VALUE,                                             0,                                            PAGE_READWRITE,                                            0,                                            MAX_FILE_MAPPING_LENGTH,                                            strFileMappingName); assert(m_hFileMapping);    if (NO_ERROR == GetLastError())    {        void * hMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);  assert(hMapView);        MY_FILE_MAPPING_INFO * pstFileMappingInfo = (MY_FILE_MAPPING_INFO *)hMapView;        memset(pstFileMappingInfo, 0, sizeof(MY_FILE_MAPPING_INFO));        UnmapViewOfFile(hMapView);    }    m_hSemReaders       = CreateSemaphore(NULL, 0, MAXLONG, strSemReadersName);    assert(m_hSemReaders);    m_hSemWriters       = CreateSemaphore(NULL, 0, MAXLONG, strSemWritersName);   assert(m_hSemWriters);    ReleaseMutex(m_hMutex);}CMyLock::~CMyLock(){    CloseHandle(m_hSemWriters);    CloseHandle(m_hSemReaders);    CloseHandle(m_hFileMapping);    CloseHandle(m_hMutex);}void CMyLock::ReadStart(){    WaitForSingleObject(m_hMutex, INFINITE);    void * hMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);  assert(hMapView);    MY_FILE_MAPPING_INFO * pstFileMappingInfo = (MY_FILE_MAPPING_INFO *)hMapView;   assert(pstFileMappingInfo);    bool bWait = (pstFileMappingInfo->m_nActiveWriters | pstFileMappingInfo->m_nWaitingWriters);    if (bWait)  // 读比写的优先级低,所以由Waiting的Writers,那么Reader等待    {        pstFileMappingInfo->m_nWaitingReaders++;    }    else    {        pstFileMappingInfo->m_nActiveReaders++;    }    UnmapViewOfFile(hMapView);    ReleaseMutex(m_hMutex);    if (bWait)  // 等待WriteEnd释放m_hSemReaders信号量    {        WaitForSingleObject(m_hSemReaders, INFINITE);    }}void CMyLock::ReadEnd(){    WaitForSingleObject(m_hMutex, INFINITE);    void * hMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);  assert(hMapView);    MY_FILE_MAPPING_INFO * pstFileMappingInfo = (MY_FILE_MAPPING_INFO *)hMapView;   assert(pstFileMappingInfo);    pstFileMappingInfo->m_nActiveReaders--;    void *  hTempSem            = NULL;    int     nReleaseSemCount    = 0;    if (0 == pstFileMappingInfo->m_nActiveReaders)  // 所有读取者读取动作完成,需要释放信号量让其他对象获得权限    {        if (0 < pstFileMappingInfo->m_nWaitingWriters)      // 写入者优先级高        {            pstFileMappingInfo->m_nWaitingWriters--;            pstFileMappingInfo->m_nActiveWriters++;         // 相当于m_nActiveWriters = 1            hTempSem            = m_hSemWriters;            nReleaseSemCount    = 1;    // 一次释放一个写入信号量        }        else if (0 < pstFileMappingInfo->m_nWaitingReaders)        {            pstFileMappingInfo->m_nActiveReaders    = pstFileMappingInfo->m_nWaitingReaders;            pstFileMappingInfo->m_nWaitingReaders   = 0;            hTempSem            = m_hSemReaders;            nReleaseSemCount    = pstFileMappingInfo->m_nActiveReaders; // 一次性释放所有读取信号量        }    }    UnmapViewOfFile(hMapView);    ReleaseMutex(m_hMutex);    if (hTempSem)    {        ReleaseSemaphore(hTempSem, nReleaseSemCount, NULL);    }}void CMyLock::WriteStart(){    WaitForSingleObject(m_hMutex, INFINITE);    void * hMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);  assert(hMapView);    MY_FILE_MAPPING_INFO * pstFileMappingInfo = (MY_FILE_MAPPING_INFO *)hMapView;   assert(pstFileMappingInfo);    bool bWait = (pstFileMappingInfo->m_nActiveReaders | pstFileMappingInfo->m_nActiveWriters | pstFileMappingInfo->m_nWaitingWriters);    if (bWait)  // 读比写的优先级低,所以不用管是否有Waiting状态的Readers    {        pstFileMappingInfo->m_nWaitingWriters++;    }    else    {        pstFileMappingInfo->m_nActiveWriters++;    }    UnmapViewOfFile(hMapView);    ReleaseMutex(m_hMutex);    if (bWait)  // 读比写的优先级低,所以不用管是否有Waiting状态的Readers    {        WaitForSingleObject(m_hSemWriters, INFINITE);    }}void CMyLock::WriteEnd(){    WaitForSingleObject(m_hMutex, INFINITE);    void * hMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);  assert(hMapView);    MY_FILE_MAPPING_INFO * pstFileMappingInfo = (MY_FILE_MAPPING_INFO *)hMapView;   assert(pstFileMappingInfo);    pstFileMappingInfo->m_nActiveWriters--;    void *  hTempSem            = NULL;    int     nReleaseSemCount    = 0;    if (0 == pstFileMappingInfo->m_nActiveWriters)  // 本次写入完成,需要释放信号量让其他对象获得权限    {        if (0 < pstFileMappingInfo->m_nWaitingWriters)      // 写入者优先级高        {            pstFileMappingInfo->m_nWaitingWriters--;            pstFileMappingInfo->m_nActiveWriters++;         // 相当于m_nActiveWriters = 1            hTempSem            = m_hSemWriters;            nReleaseSemCount    = 1;    // 一次释放一个写入信号量        }        else if (0 < pstFileMappingInfo->m_nWaitingReaders)        {            pstFileMappingInfo->m_nActiveReaders    = pstFileMappingInfo->m_nWaitingReaders;            pstFileMappingInfo->m_nWaitingReaders   = 0;            hTempSem            = m_hSemReaders;            nReleaseSemCount    = pstFileMappingInfo->m_nActiveReaders; // 一次性释放所有读取信号量        }    }    UnmapViewOfFile(hMapView);    ReleaseMutex(m_hMutex);    if (hTempSem)    {        ReleaseSemaphore(hTempSem, nReleaseSemCount, NULL);    }}
原创粉丝点击