单写入多读取进程锁
来源:互联网 发布:杀死汝爱真实事件 知乎 编辑:程序博客网 时间: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); }}
阅读全文
0 0
- 单写入多读取进程锁
- 多进程写入文件
- memcache队列类 支持多进程并发写入、读取 边写边读,AB面轮值替换
- RevitAPI进阶之独立进程内读取、写入Revit文件.
- 单进程 vs 多进程
- Python多进程写入同一文件
- Python多进程写入同一文件
- 关于BEA-000402和BEA-000438(没有进程来读取写入管道的数据)
- 关于BEA-000402和BEA-000438(没有进程来读取写入管道的数据)
- 读取写入文件
- JS读取写入COOKIE
- 写入与读取
- java写入/读取xml
- .net XML 读取 写入
- C# 读取写入文件
- 写入读取Cookie值
- xml读取和写入
- 文本文件读取和写入
- 网络编程(2)-socket
- Mysql数据库引擎区别
- 进程间的通信---共享内存
- jquery学习记录3
- TCP和UDP的区别
- 单写入多读取进程锁
- 二进制
- TCP协议发送文件小案例
- 解决网页响应慢,waiting(TTFB)时间过长
- java基础的积累巩固--类加载顺序
- TreeSet
- Ubuntu下查看jdk安装路径
- 获取Windows系统注册的文件类型和图标
- C++中模板使用详解