多线程的对象生命周期管理十分繁杂
对于构造函数的要求:1.不在构造函数中注册回调函数
2.不将对象的this指针传给跨线程函数
原因:多线程环境下将this指针暴露将会使得其他线程访问到半成品的对象
解决方案:使用二段式的初始化 ,既先构造然后初始操作
对于析构函数,多线程的析构将是一个头疼的问题:mutex对于析构的保护是无效的,因为mutex将会 在析构函数中被销毁
原始指针管理对象的繁杂性不适合多线程的编程环境,智能指针能够很好的解决这个问题
c++程序的内存泄露问题来自以下几个方面:
1.缓冲区溢出(使用容器vector来管理解决)
2.空指针,野指针(智能指针)
3.重复释放(智能指针)
4.内存泄露(智能指针)
5.不配对的new[]和/delete(容器)
智能指针的线程安全性:智能指针本身不是线程安全的,一个实体能够被两个线程同时读取,两个shared_ptr能够同时被两个线程写入(析构操作),多个线程同时读写shared_ptr需要加上锁
样例如下
std::shared_ptr<int> totalPtr = make_shared<int>(30);
void reader(){
std::shared_ptr<int> localPtr;
{
/// mutex scope use { to minize it
std::unique_lock<std::mutex> lk(sharedMutex);
localPtr = totalPtr;
}
///some read
}
void writer(){
///outer the create op out of scope
std::shared_ptr<int> newPtr = make_shared<int> (4);
{
unique_lock<mutex> lk(sharedMutex);
///may be reser
std::shared_ptr<int> Ptr = totalPtr;
totalPtr = newPtr;
}
///some func
}
要点在于将对象的创建与销毁放到临界区之外,减少临界区长度
shared_ptr技术的陷阱: 存放在容器中(除非从容器中删除,否则资源泄露)
bind函数(会被bind拷贝一份,导致生命周期的延长)
的特点:析构函数在创建时就被捕获(不在需要虚析构,但仍然建议)
shared_ptr<void>可以存放任何类型的指针
讨论:shared_ptr导致对象的创建和析构可能不在一个线程中,可以用一个专门的线程来进行析操作(防止关键操作被拖慢)
shared_ptr同样是现成的RAII handler(被new出来之后不delete,而是交给handler)
避免循环引用:父拥有子对象的shared_ptr,子对象拥有父对象的weak_ptr
利用shared_ptr实现的线程池技术,定制shared_ptr的析构函数
enable_sharead_from_this:被暴露的this指针能够接着被shared_ptr管理
弱回调技术:weak_ptr+每次使用前check对象是否存活
弱回调技术代码示例,对象容器
class ObjectFactory :public enable_shared_from_this<ObjectFactory>
{
public:
ObjectFactory(){
}
~ObjectFactory(){
cout<<"Fac be deleted"<<endl;
}
std::shared_ptr<Obj> get(const int &key){
shared_ptr<Obj> localPtr;
unique_lock<mutex> lk(m_mux);
auto & wkPtr = m_map[key];
localPtr = wkPtr.lock();
if(!localPtr){
localPtr.reset(new Obj(key),std::bind(&ObjectFactory::remove,std::weak_ptr<ObjectFactory>(shared_from_this()),std::placeholders::_1));
wkPtr = localPtr;
}
return localPtr;
}
static void remove(std::weak_ptr<ObjectFactory>& fac,Obj*obj){
shared_ptr<ObjectFactory> factr = fac.lock();
if(factr){
factr->deleteObj(obj);
}
}
void deleteObj(Obj *obj){
if(obj){
unique_lock<mutex> lk(m_mux);
m_map.erase(obj->key);
}
delete obj;
}
private:
map<int,std::weak_ptr<Obj> > m_map;
mutex m_mux;
};
被管理对象
class Obj{
public:
Obj(int key)
:key(key)
{};
~Obj(){
cout<<"obj be removed"<<endl;
}
int key;
private:
std::weak_ptr<ObjectFactory> m_fac;
};