当前位置:网站首页>Multi-threaded mutex application RAII mechanism
Multi-threaded mutex application RAII mechanism
2022-07-30 20:02:00 【a ray of sunshine】
什么是RAII机制
RAII是Resource Acquisition Is Initialization(翻译成 “资源获取即初始化”)的简称,是C++语言的一种管理资源、To avoid resource leaks usage,The method is dependent on the constructor endowment and the destructor execution mechanism.
RAIIApproach is to use a class object,In the constructor of the object access to resources,在对象生命期内控制对资源的访问,Finally in the object disappears,Its destructor to release the access to resources;
这里的资源可以是文件句柄,内存,Event,互斥量等等,由于系统的资源是有限的,就好比自然界的石油,铁矿一样,不是取之不尽,用之不竭的.所以,We in programming security,Request must follow the following steps:
申请资源
使用资源
释放资源
In step 1 and step 2,We usually are relatively easy to grasp,And the release of resources will be overlooked because various coding,Lead to system resources not actually used,But not to release or cause other problems,Affect the system resource utilization.
没有使用RAII机制的弊端
So why do we involve resource management,建议使用RAIICoding mechanism?
You can view the code of the following two articles,I'm in these two articles are directly using the systemAPI进行资源操作,没有使用RAIIMechanism of resource management,In the code to read and maintain all very inconvenient.
Multithreaded deadlock and solve
Using the key code for thread synchronization
Don't recommend encoding clips:
while (TRUE)
{
//Wait until get the ownership of the specified object
EnterCriticalSection(&g_csLock);
//关键代码段-begin
if (g_nIndex++ < nMaxCnt)
{
cout << "Index = "<< g_nIndex << " ";
cout << "Thread2 is runing" << endl;
//权限释放,容易忘记
LeaveCriticalSection(&g_csLock);
}
else
{
//权限释放,容易忘记
LeaveCriticalSection(&g_csLock);
//关键代码段-end
break;
}
}
This encoding is not recommended becauseEnterCriticalSection/LeaveCriticalSection必须配对使用,Very need to rely on a person,Can't fundamentally solve the problem,如果LeaveCriticalSectionFunctions are not performed or forget to add theAPI很容易引发问题.
The mutex applicationRAII机制
为了从根本上解决问题,Reduce artificial factors causing application system problem or resource leak,The key code and the mutex lock both demonstrated how to applyRAII机制,Simplify the multi-threading mutex code.
Initialization and lock key code interface:
class CSLock
{
public:
CSLock()
{
//When the constructor to initialize the key code object,获取资源
InitializeCriticalSection(&m_csLock);
}
~CSLock()
{
//Released when the destructor for key code object allocation of all resources,释放资源
DeleteCriticalSection(&m_csLock);
}
//Objects within the life cycle of the management of resources(Lock/Unlock),使用资源
void Lock()
{
EnterCriticalSection(&m_csLock);
}
void Unlock()
{
LeaveCriticalSection(&m_csLock);
}
//Stop lock copy and assignment
private:
CSLock (const CSLock& );
CSLock& operator = (const CSLock&);
private:
CRITICAL_SECTION m_csLock;
};
Create a mutex object and lock interface:
class CMutexLock
{
public:
CMutexLock()
{
m_hMutex = CreateMutex(NULL, FALSE, NULL);//获取资源
}
~CMutexLock()
{
CloseHandle(m_hMutex);//释放资源
}
void Lock()
{
WaitForSingleObject(m_hMutex, INFINITE);//使用资源
}
void Unlock()
{
ReleaseMutex(m_hMutex);//使用资源
}
//Stop lock copy and assignment
private:
CMutexLock(const CMutexLock&);
CMutexLock& operator= (const CMutexLock&);
private:
HANDLE m_hMutex;
};
类模板对象,再一次使用RAIIManagement mechanism of lock objects take up and release,Suggest to simplify lock application,Implement automatic recycling resources
template<class T>
class CLockGuard
{
public:
CLockGuard(T& locker) :m_lockerObj(locker)
{
m_lockerObj.Lock();
}
~CLockGuard()
{
m_lockerObj.Unlock();
}
private:
T& m_lockerObj; //必须是引用类型 Ensure to use the global lock,否则锁不住
};
具体示例:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <Windows.h>
//创建全局锁,Ensure that the lock is a
CSLock g_csLock;
CMutexLock g_Mutex;
//全局数据
int g_nIndex = 0;
const int nMaxCnt = 30;
BOOL AddNum(int tid)
{
BOOL bRet = TRUE;
//RAII用法,创建lockObject at the same time performlock操作,Destructor after automatic callunlock操作,Avoid man-made missing
CLockGuard<CMutexLock> lock(g_Mutex);
if (g_nIndex++ < nMaxCnt)
{
std::cout << "Index = " << g_nIndex << " ";
std::cout << "thread " << tid << " is runing" << std::endl;
}
else
{
bRet = FALSE;
}
return bRet;
}
//线程函数1
DWORD WINAPI Thread1(LPVOID lpParameter)
{
while (true)
{
if (!AddNum(1))
{
break;
}
}
return 0;
}
//线程函数2
DWORD WINAPI Thread2(LPVOID lpParameter)
{
while (true)
{
if (!AddNum(2))
{
break;
}
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE harThread[2] = {NULL,NULL};
//创建新的线程
harThread[0] = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);//立即执行
harThread[1] = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);//立即执行
WaitForMultipleObjects(2, harThread, TRUE, INFINITE);
//良好的编码习惯
for (int i = 0; i < 2; i++)
{
CloseHandle(harThread[i]);
}
return 0;
}
运行效果:
从输出结果上看,Our lock is effective,No confusion.这里使用了CLockGuardTemplate class to further simplify multithreaded code lock,Both realized the code reuse and guarantee the security coding.其实,This encoding inC++11中lock_guardHas been applied to the system.点击这里查看lock_guard(lock_guard - C++ Reference).
边栏推荐
- Database indexes: indexes are not a panacea
- After watching "Second Uncle", I was even more internalized
- MySQL性能优化(硬件,系统配置,表结构,SQL语句)
- 用jOOQ 3.17投射类型安全的嵌套表记录
- MindSpore:【MindSpore1.1】Mindspore安装后验证出现cudaSetDevice failed错误
- 对int变量赋值的操作是原子的吗?
- 时间复杂度与空间复杂度
- Download and installation of the latest version of MySQL 8.0 under Linux (detailed steps)
- MindSpore:【Resolve node failed】解析节点失败的问题
- halcon——轮廓线
猜你喜欢
MySQL performance optimization (hardware, system configuration, table structure, SQL statements)
Maxwell 一款简单易上手的实时抓取Mysql数据的软件
“数字化重构系统,搞定 CEO 是第一步”
Recommended system: cold start problem [user cold start, item cold start, system cold start]
LeetCode 0952.按公因数计算最大组件大小:建图 / 并查集
Cesium加载离线地图和离线地形
Linux download and install mysql5.7 version tutorial the most complete and detailed explanation
Linux下最新版MySQL 8.0的下载与安装(详细步骤)
The JDBC programming of the MySQL database
MindSpore:【Resolve node failed】解析节点失败的问题
随机推荐
Database Tuning - Database Tuning
MySQL大总结
MySQL夺命10问,你能坚持到第几问?
为单行查询设置JDBC Statement.setFetchSize()为1的方法指南
Start background services across processes
刷题记录----字符串
ImportError: attempted relative import with no known parent package
推荐系统:冷启动问题【用户冷启动、物品冷启动、系统冷启动】
Maxwell 一款简单易上手的实时抓取Mysql数据的软件
[flink] Error finishing Could not instantiate the executor. Make sure a planner module is on the classpath
ImportError:attempted relative import with no known parent package
普通的int main(){}没有写return 0;会怎么样?
Different lower_case_table_names settings for server (‘1‘) and data dictionary (‘0‘) 解决方案
推荐系统:评估指标【离线评估指标:RMSE(均方根误差)、AUC、准确率、召回率、F1】【在线评估:A/B测试】【一般要求响应时间<0.5s】
el-input can only input integers (including positive numbers, negative numbers, 0) or only integers (including positive numbers, negative numbers, 0) and decimals
Install Mysql5.7 under Linux, super detailed and complete tutorial, and cloud mysql connection
M3SDA: Moment matching for multi-source domain adaptation
el-input 只能输入整数(包括正数、负数、0)或者只能输入整数(包括正数、负数、0)和小数
MindSpore:【resnet_thor模型】尝试运行resnet_thor时报Could not convert to
coming!Dongfang Selection brings goods to the live broadcast of Longjiang agricultural products