Muduo学习历程,线程安全的对象管理

多线程的对象生命周期管理十分繁杂

对于构造函数要求: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;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值